示例#1
0
/* Initiate an SSL handshake on this stream and encrypt all subsequent data */
int stream_enable_ssl(PTSTREAM *pts) {
#ifdef USE_SSL
	SSL_METHOD *meth;
	SSL *ssl;
	SSL_CTX *ctx;
	
	/* Initialise the connection */
	SSLeay_add_ssl_algorithms();
	meth = TLSv1_client_method();
	SSL_load_error_strings();

	ctx = SSL_CTX_new (meth);
	ssl = SSL_new (ctx);
	SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
	SSL_set_wfd (ssl, stream_get_outgoing_fd(pts));	
	SSL_connect (ssl);

	/* Store ssl and ctx parameters */
	pts->ssl = ssl;
	pts->ctx = ctx;
#else
	message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection");
#endif /* USE_SSL */

	return 1;
}
示例#2
0
int sycSSL_set_wfd(SSL *ssl, int fd) {
   int result;
   Debug2("SSL_set_wfd(%p, %d)", ssl, fd);
   result = SSL_set_wfd(ssl, fd);
   Debug1("SSL_set_wfd() -> %d", result);
   return result;
}
示例#3
0
/* Initiate an SSL handshake on this stream and encrypt all subsequent data */
int stream_enable_ssl(PTSTREAM *pts) {
#ifdef USE_SSL
	SSL *ssl;
	SSL_CTX *ctx;
	int ret;

	/* Initialise the connection */
	SSLeay_add_ssl_algorithms();
	SSL_load_error_strings();

	ctx = SSL_CTX_new (SSLv3_client_method());
	ssl = SSL_new (ctx);

	if (args_info.verbose_flag) {
		message("Set SNI hostname to %s\n", args_info.proxyhost_arg);
	}
	ret = SSL_set_tlsext_host_name(ssl, args_info.proxyhost_arg);
	if (!ret) {
		message("TLS SNI error, giving up: SSL_set_tlsext_host_name failed\n");
		exit(1);
	}

	SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
	SSL_set_wfd (ssl, stream_get_outgoing_fd(pts));	
	SSL_connect (ssl);

	/* Store ssl and ctx parameters */
	pts->ssl = ssl;
	pts->ctx = ctx;
#else
	message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection");
#endif /* USE_SSL */

	return 1;
}
示例#4
0
SSLConnection::SSLConnection(SSL *ssl, int rfd, int wfd)
    : m_ssl(ssl)
    , m_iStatus(DISCONNECTED)
    , m_iWant(0)
{
    SSL_set_rfd(m_ssl, rfd);
    SSL_set_wfd(m_ssl, wfd);
}
示例#5
0
int SSLConnection::setfd(int rfd, int wfd)
{
    m_iWant = 0;
    int ret = SSL_set_rfd(m_ssl, rfd);
    if (!ret)
        return ret == 0;
    m_iStatus = DISCONNECTED;

    return SSL_set_wfd(m_ssl, wfd) == 0;
}
示例#6
0
文件: tls_server.c 项目: kitche/httpd
int
tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write)
{
	struct tls *conn_ctx = *cctx;
	int ret, err;
	
	if ((ctx->flags & TLS_SERVER) == 0) {
		tls_set_error(ctx, "not a server context");
		goto err;
	}

	if (conn_ctx == NULL) {
		if ((conn_ctx = tls_server_conn(ctx)) == NULL) {
			tls_set_error(ctx, "connection context failure");
			goto err;
		}
		*cctx = conn_ctx;

		if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
			tls_set_error(ctx, "ssl failure");
			goto err;
		}

		if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 ||
		    SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) {
			tls_set_error(ctx, "ssl set fd failure");
			goto err;
		}
		SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx);
	}

	if ((ret = SSL_accept(conn_ctx->ssl_conn)) != 1) {
		err = tls_ssl_error(ctx, conn_ctx->ssl_conn, ret, "accept");
		if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) {
			return (err);
		}
		goto err;
	}

	return (0);

err:
	return (-1);
}
示例#7
0
/* Initiate an SSL handshake on this stream and encrypt all subsequent data */
int stream_enable_ssl(PTSTREAM *pts) {
#ifdef USE_SSL
	const SSL_METHOD *meth;
	SSL *ssl;
	SSL_CTX *ctx;
	long res = 1;
	
	/* Initialise the connection */
	SSLeay_add_ssl_algorithms();
	if (args_info.enforcetls1_flag) {
		meth = TLSv1_client_method();
	} else {
		meth = SSLv23_client_method();
	}
	SSL_load_error_strings();

	ctx = SSL_CTX_new (meth);
	ssl = SSL_new (ctx);
	
	SSL_set_rfd (ssl, stream_get_incoming_fd(pts));
	SSL_set_wfd (ssl, stream_get_outgoing_fd(pts));	

	/* SNI support */
	if ( args_info.verbose_flag ) {
           message( "Set SNI hostname to %s\n", args_info.proxyhost_arg );
    }
	res = SSL_set_tlsext_host_name(ssl,args_info.proxyhost_arg);
	if (res < 0) {
	   message( "TLS SNI error, giving up: SSL_set_tlsext_host_name returned error message:\n  %u\n", res );
	   exit( 1 );
	}
	
	SSL_connect (ssl);

	/* Store ssl and ctx parameters */
	pts->ssl = ssl;
	pts->ctx = ctx;
#else
	message("Warning: stream_open(): SSL stream requested but no SSL support available; using unencrypted connection");
#endif /* USE_SSL */

	return 1;
}
示例#8
0
int
tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write)
{
	struct tls *conn_ctx = NULL;

	if ((ctx->flags & TLS_SERVER) == 0) {
		tls_set_errorx(ctx, "not a server context");
		goto err;
	}

	if ((conn_ctx = tls_server_conn(ctx)) == NULL) {
		tls_set_errorx(ctx, "connection context failure");
		goto err;
	}

	if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
		tls_set_errorx(ctx, "ssl failure");
		goto err;
	}
	if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) {
		tls_set_errorx(ctx, "ssl application data failure");
		goto err;
	}
	if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 ||
	    SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) {
		tls_set_errorx(ctx, "ssl file descriptor failure");
		goto err;
	}

	*cctx = conn_ctx;

	return (0);

 err:
	tls_free(conn_ctx);

	*cctx = NULL;

	return (-1);
}
示例#9
0
文件: siobuf.c 项目: staceyson/balsa
int
sio_set_tlsserver_ssl (struct siobuf *sio, SSL *ssl)
{
  int ret;

  assert (sio != NULL);

  if (ssl != NULL)
    {
      sio->ssl = ssl;
      SSL_set_rfd (sio->ssl, sio->sdr);
      SSL_set_wfd (sio->ssl, sio->sdw);
      while ((ret = SSL_accept (sio->ssl)) <= 0)
        if (sio_sslpoll (sio, ret) <= 0)
	  {
	    SSL_free (sio->ssl);
	    sio->ssl = NULL;
	    break;
	  }
      sio_set_timeout (sio, sio->milliseconds);
    }
  return sio->ssl != NULL;
}
示例#10
0
int
tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
    const char *servername)
{
	int rv = -1;

	if (fd_read < 0 || fd_write < 0) {
		tls_set_errorx(ctx, "invalid file descriptors");
		goto err;
	}

	if (tls_connect_common(ctx, servername) != 0)
		goto err;

	if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 ||
	    SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) {
		tls_set_errorx(ctx, "ssl file descriptor failure");
		goto err;
	}

	rv = 0;
 err:
	return (rv);
}
示例#11
0
文件: client.c 项目: l7s/stunnel
static void init_local(CLI *c) {
    SOCKADDR_UNION addr;
    socklen_t addrlen;

    addrlen=sizeof addr;
    if(getpeername(c->local_rfd.fd, &addr.sa, &addrlen)<0) {
        strcpy(c->accepted_address, "NOT A SOCKET");
        c->local_rfd.is_socket=0;
        c->local_wfd.is_socket=0; /* TODO: It's not always true */
#ifdef USE_WIN32
        if(get_last_socket_error()!=ENOTSOCK) {
#else
        if(c->opt->option.transparent_src || get_last_socket_error()!=ENOTSOCK) {
#endif
            sockerror("getpeerbyname");
            longjmp(c->err, 1);
        }
        /* ignore ENOTSOCK error so 'local' doesn't have to be a socket */
    } else { /* success */
        /* copy addr to c->peer_addr */
        memcpy(&c->peer_addr.addr[0], &addr, sizeof addr);
        c->peer_addr.num=1;
        s_ntop(c->accepted_address, &c->peer_addr.addr[0]);
        c->local_rfd.is_socket=1;
        c->local_wfd.is_socket=1; /* TODO: It's not always true */
        /* it's a socket: lets setup options */
        if(set_socket_options(c->local_rfd.fd, 1)<0)
            longjmp(c->err, 1);
#ifdef USE_LIBWRAP
        libwrap_auth(c);
#endif /* USE_LIBWRAP */
        auth_user(c);
        s_log(LOG_NOTICE, "Service %s accepted connection from %s",
            c->opt->servname, c->accepted_address);
    }
}

static void init_remote(CLI *c) {
    /* create connection to host/service */
    if(c->opt->source_addr.num)
        memcpy(&c->bind_addr, &c->opt->source_addr, sizeof(SOCKADDR_LIST));
#ifndef USE_WIN32
    else if(c->opt->option.transparent_src)
        memcpy(&c->bind_addr, &c->peer_addr, sizeof(SOCKADDR_LIST));
#endif
    else {
        c->bind_addr.num=0; /* don't bind connecting socket */
    }

    /* setup c->remote_fd, now */
    if(c->opt->option.remote)
        c->remote_fd.fd=connect_remote(c);
#ifdef SO_ORIGINAL_DST
    else if(c->opt->option.transparent_dst)
        c->remote_fd.fd=connect_transparent(c);
#endif /* SO_ORIGINAL_DST */
    else /* NOT in remote mode */
        c->remote_fd.fd=connect_local(c);
    c->remote_fd.is_socket=1; /* always! */
    s_log(LOG_DEBUG, "Remote FD=%d initialized", c->remote_fd.fd);
    if(set_socket_options(c->remote_fd.fd, 2)<0)
        longjmp(c->err, 1);
}

static void init_ssl(CLI *c) {
    int i, err;
    SSL_SESSION *old_session;

    if(!(c->ssl=SSL_new(c->opt->ctx))) {
        sslerror("SSL_new");
        longjmp(c->err, 1);
    }
    SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */
    SSL_set_session_id_context(c->ssl, (unsigned char *)sid_ctx,
        strlen(sid_ctx));
    if(c->opt->option.client) {
#ifndef OPENSSL_NO_TLSEXT
        if(c->opt->host_name) {
            s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->host_name);
            if(!SSL_set_tlsext_host_name(c->ssl, c->opt->host_name)) {
                sslerror("SSL_set_tlsext_host_name");
                longjmp(c->err, 1);
            }
        }
#endif
        if(c->opt->session) {
            enter_critical_section(CRIT_SESSION);
            SSL_set_session(c->ssl, c->opt->session);
            leave_critical_section(CRIT_SESSION);
        }
        SSL_set_fd(c->ssl, c->remote_fd.fd);
        SSL_set_connect_state(c->ssl);
    } else {
        if(c->local_rfd.fd==c->local_wfd.fd)
            SSL_set_fd(c->ssl, c->local_rfd.fd);
        else {
           /* does it make sence to have SSL on STDIN/STDOUT? */
            SSL_set_rfd(c->ssl, c->local_rfd.fd);
            SSL_set_wfd(c->ssl, c->local_wfd.fd);
        }
        SSL_set_accept_state(c->ssl);
    }

    /* setup some values for transfer() function */
    if(c->opt->option.client) {
        c->sock_rfd=&(c->local_rfd);
        c->sock_wfd=&(c->local_wfd);
        c->ssl_rfd=c->ssl_wfd=&(c->remote_fd);
    } else {
        c->sock_rfd=c->sock_wfd=&(c->remote_fd);
        c->ssl_rfd=&(c->local_rfd);
        c->ssl_wfd=&(c->local_wfd);
    }

    while(1) {
#if OPENSSL_VERSION_NUMBER<0x1000002f
        /* this critical section is a crude workaround for CVE-2010-3864 *
         * see http://www.securityfocus.com/bid/44884 for details        *
         * NOTE: this critical section also covers callbacks (e.g. OCSP) */
        enter_critical_section(CRIT_SSL);
#endif /* OpenSSL version < 1.0.0b */
        if(c->opt->option.client)
            i=SSL_connect(c->ssl);
        else
            i=SSL_accept(c->ssl);
#if OPENSSL_VERSION_NUMBER<0x1000002f
        leave_critical_section(CRIT_SSL);
#endif /* OpenSSL version < 1.0.0b */
        err=SSL_get_error(c->ssl, i);
        if(err==SSL_ERROR_NONE)
            break; /* ok -> done */
        if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) {
            s_poll_init(&c->fds);
            s_poll_add(&c->fds, c->ssl_rfd->fd,
                err==SSL_ERROR_WANT_READ,
                err==SSL_ERROR_WANT_WRITE);
            switch(s_poll_wait(&c->fds, c->opt->timeout_busy, 0)) {
            case -1:
                sockerror("init_ssl: s_poll_wait");
                longjmp(c->err, 1);
            case 0:
                s_log(LOG_INFO, "init_ssl: s_poll_wait:"
                    " TIMEOUTbusy exceeded: sending reset");
                longjmp(c->err, 1);
            case 1:
                break; /* OK */
            default:
                s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result");
                longjmp(c->err, 1);
            }
            continue; /* ok -> retry */
        }
        if(err==SSL_ERROR_SYSCALL) {
            switch(get_last_socket_error()) {
            case EINTR:
            case EAGAIN:
                continue;
            }
        }
        if(c->opt->option.client)
            sslerror("SSL_connect");
        else
            sslerror("SSL_accept");
        longjmp(c->err, 1);
    }
    if(SSL_session_reused(c->ssl)) {
        s_log(LOG_INFO, "SSL %s: previous session reused",
            c->opt->option.client ? "connected" : "accepted");
    } else { /* a new session was negotiated */
        if(c->opt->option.client) {
            s_log(LOG_INFO, "SSL connected: new session negotiated");
            enter_critical_section(CRIT_SESSION);
            old_session=c->opt->session;
            c->opt->session=SSL_get1_session(c->ssl); /* store it */
            if(old_session)
                SSL_SESSION_free(old_session); /* release the old one */
            leave_critical_section(CRIT_SESSION);
        } else
            s_log(LOG_INFO, "SSL accepted: new session negotiated");
        print_cipher(c);
    }
}
示例#12
0
/* run as if invoked by inetd */
int main (int argc, char *argv[])
{
    int c;
    int filetype = SSL_FILETYPE_PEM;
    char *peer = NULL;
    char *ptr;
    char buf[4096];
    enum optype op = NOOP;
    char *setkey = NULL;
    SSL_CTX *ctx;
    X509 *client_cert;
    int r;
    pool *p = NULL;
    security_context *context = NULL;
    int max_wait = 0;

    while ((c = getopt (argc, argv, "apc:k:C:D:f:")) != -1) {
        switch (c) {
        case 'a':
            filetype = SSL_FILETYPE_ASN1;
            break;

        case 'p':
            filetype = SSL_FILETYPE_PEM;
            break;

        case 'c':
            /* 'optarg' is the certificate file */
            certfile = strdup (optarg);
            break;

        case 'k':
            /* 'optarg' is the key file */
            keyfile = strdup (optarg);
            break;

        case 'C':
            /* 'optarg' is the CA we accept */
            cafile = strdup (optarg);
            break;

        case 'D':
            /* 'optarg' is a directory of CAs */
            cadir = strdup (optarg);
            break;

        case 'f':
            configfile = strdup (optarg);
            break;

        case '?':
        default:
            usage ();
            break;
        }
    }

    libpbc_config_init (p, configfile, "keyserver");
    pbc_log_init_syslog (p, "keyserver");
    libpbc_pubcookie_init (p, &context);

    debug = libpbc_config_getint (p, "logging_level", 0);
    if (!keyfile)
        keyfile =
            libpbc_config_getstring (p, "ssl_key_file", "server.pem");
    if (!certfile)
        certfile =
            libpbc_config_getstring (p, "ssl_cert_file", "server.pem");
    if (!cafile)
        cafile = libpbc_config_getstring (p, "ssl_ca_file", NULL);
    if (!cadir)
        cadir = libpbc_config_getstring (p, "ssl_ca_path", NULL);

    gcfile = libpbc_config_getstring (p, "granting_cert_file", NULL);
    max_wait = libpbc_config_getint (p, "keyserver_max_wait_time", 0);
    if (max_wait < 0)
        max_wait = 0;

    /* xxx log connection information */

    /* initalize the PRNG as best we can if we have to */
    if (RAND_status () == 0) {
        pbc_time_t t = pbc_time (NULL);
        pid_t pid = getpid ();
        char buf[1024];
        char *cmd[3] = { "/bin/ps", "-ef", NULL };

        RAND_seed ((unsigned char *) &t, sizeof (t));
        RAND_seed ((unsigned char *) &pid, sizeof (pid));

        capture_cmd_output (p, cmd, buf, sizeof (buf));
        RAND_seed ((unsigned char *) buf, sizeof (buf));
    }

    /* Load SSL Error Strings */
    SSL_load_error_strings ();

    /* initialize the OpenSSL connection */
    SSL_library_init ();

    ctx = SSL_CTX_new (TLSv1_server_method ());

    /* setup the correct certificate */
    if (!SSL_CTX_use_certificate_file (ctx, certfile, filetype)) {
        logerrstr ("SSL_CTX_use_certificate_file");
        exit (1);
    }
    if (!SSL_CTX_use_PrivateKey_file (ctx, keyfile, filetype)) {
        logerrstr ("SSL_CTX_use_PrivateKey_file");
        exit (1);
    }
    if (!SSL_CTX_load_verify_locations (ctx, cafile, cadir)) {
        logerrstr ("SSL_CTX_load_verify_locations");
        exit (1);
    }

    SSL_CTX_set_verify (ctx,
                        SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT
                        | SSL_VERIFY_CLIENT_ONCE, verify_callback);

    ssl = SSL_new (ctx);

    /* negotiate SSL */
    SSL_set_rfd (ssl, 0);
    SSL_set_wfd (ssl, 1);
    SSL_set_accept_state (ssl);

    /* If no data in max_wait seconds, give up */
    if (max_wait) {
        signal (SIGALRM, sig_alarm);
        alarm (max_wait);
    }

    if (SSL_accept (ssl) <= 0) {
        logerrstr ("SSL_accept");
        ERR_print_errors_fp (stderr);
        exit (1);
    }
    if (max_wait)
        alarm (0);

    /* check certificate */
    client_cert = SSL_get_peer_certificate (ssl);
    if (client_cert == NULL) {
        pbc_log_activity (p, PBC_LOG_ERROR, "client_cert == NULL???");
        exit (1);
    }

    peer = get_cn_from_crt (client_cert);
    if (peer == NULL) {
        pbc_log_activity (p, PBC_LOG_ERROR, "peer == NULL???");
        exit (1);
    }

    pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "peer cn: %s\n", peer);

    /* read HTTP query */
    if ((c=SSL_read (ssl, buf, sizeof(buf)-1)) <= 0) {
        pbc_log_activity (p, PBC_LOG_ERROR, "SSL_read() failed");
        ERR_print_errors_fp (stderr);
        exit (1);
    }
    buf[c] = '\0';

    pbc_log_activity (p, PBC_LOG_DEBUG_VERBOSE, "REQ=%s", buf);
    for (ptr = buf; *ptr != '\0'; ptr++) {
        if (*ptr == '?' || *ptr == '&') {       /* next arg */
            /* look for 'genkey' */
            if (!strncmp (ptr + 1, "genkey=yes", 10)) {
                op = GENKEY;
            }

            else if (!strncmp (ptr + 1, "genkey=no", 9)) {
                op = FETCHKEY;
            }

            else if (!strncmp (ptr + 1, "genkey=put", 10)) {
                op = SETKEY;
            }

            else if (!strncmp (ptr + 1, "genkey=permit", 13)) {
                op = PERMIT;
            }

            else if (!strncmp (ptr + 1, "genkey=getgc", 12)) {
                op = FETCHGC;
            }

            else if (!strncmp (ptr + 1, "genkey=setpkey", 12)) {
                op = SETPKEY;
            }

            /* look for 'setkey' */
            else if (!strncmp (ptr + 1, "setkey=", 7)) {
                char *q;

                ptr++;          /* ? or & */
                ptr += 7;       /* setkey= */

                setkey = strdup (ptr);
                /* terminated by ? - this is a bit dubious, but i think it's 
                   compensated for later - ssw */
                q = strchr (setkey, '?');
                if (q)
                    *q = '\0';
            }
        }
    }

    if (op == NOOP) {
        pbc_log_activity (p, PBC_LOG_ERROR,
                          "peer didn't specify an operation");
        exit (1);
    }

    /* call doit */

    r = doit (peer, context, op, setkey, client_cert);
    SSL_shutdown (ssl);

    return r;
}
示例#13
0
static int init_ssl(CLI *c) {
    int i, err;
    SSL_SESSION *old_session;

    if(!(c->ssl=SSL_new(ctx))) {
        sslerror("SSL_new");
        return -1;
    }
#if SSLEAY_VERSION_NUMBER >= 0x0922
    SSL_set_session_id_context(c->ssl, sid_ctx, strlen(sid_ctx));
#endif
    if(options.option.client) {
        if(c->opt->session) {
            enter_critical_section(CRIT_SESSION);
            SSL_set_session(c->ssl, c->opt->session);
            leave_critical_section(CRIT_SESSION);
        }
        SSL_set_fd(c->ssl, c->remote_fd.fd);
        SSL_set_connect_state(c->ssl);
    } else {
        if(c->local_rfd.fd==c->local_wfd.fd)
            SSL_set_fd(c->ssl, c->local_rfd.fd);
        else {
           /* Does it make sence to have SSL on STDIN/STDOUT? */
            SSL_set_rfd(c->ssl, c->local_rfd.fd);
            SSL_set_wfd(c->ssl, c->local_wfd.fd);
        }
        SSL_set_accept_state(c->ssl);
    }

    /* Setup some values for transfer() function */
    if(options.option.client) {
        c->sock_rfd=&(c->local_rfd);
        c->sock_wfd=&(c->local_wfd);
        c->ssl_rfd=c->ssl_wfd=&(c->remote_fd);
    } else {
        c->sock_rfd=c->sock_wfd=&(c->remote_fd);
        c->ssl_rfd=&(c->local_rfd);
        c->ssl_wfd=&(c->local_wfd);
    }

    while(1) {
        if(options.option.client)
            i=SSL_connect(c->ssl);
        else
            i=SSL_accept(c->ssl);
        err=SSL_get_error(c->ssl, i);
        if(err==SSL_ERROR_NONE)
            break; /* ok -> done */
        if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) {
            s_poll_zero(&c->fds);
            s_poll_add(&c->fds, c->ssl_rfd->fd,
                err==SSL_ERROR_WANT_READ,
                err==SSL_ERROR_WANT_WRITE);
            switch(s_poll_wait(&c->fds, c->opt->timeout_busy)) {
            case -1:
                sockerror("init_ssl: s_poll_wait");
                return -1; /* error */
            case 0:
                s_log(LOG_INFO, "init_ssl: s_poll_wait timeout");
                return -1; /* timeout */
            case 1:
                break; /* OK */
            default:
                s_log(LOG_ERR, "init_ssl: s_poll_wait unknown result");
                return -1; /* error */
            }
            continue; /* ok -> retry */
        }
        if(err==SSL_ERROR_SYSCALL) {
            switch(get_last_socket_error()) {
            case EINTR:
            case EAGAIN:
                continue;
            }
        }
        if(options.option.client)
            sslerror("SSL_connect");
        else
            sslerror("SSL_accept");
        return -1;
    }
    if(SSL_session_reused(c->ssl)) {
        s_log(LOG_INFO, "SSL %s: previous session reused",
            options.option.client ? "connected" : "accepted");
    } else { /* a new session was negotiated */
        if(options.option.client) {
            s_log(LOG_INFO, "SSL connected: new session negotiated");
            enter_critical_section(CRIT_SESSION);
            old_session=c->opt->session;
            c->opt->session=SSL_get1_session(c->ssl); /* store it */
            if(old_session)
                SSL_SESSION_free(old_session); /* release the old one */
            leave_critical_section(CRIT_SESSION);
        } else
            s_log(LOG_INFO, "SSL accepted: new session negotiated");
        print_cipher(c);
    }
    return 0; /* OK */
}
示例#14
0
static void init_ssl(CLI * c)
{
	int i, err;
	SSL_SESSION *old_session;

	c->ssl = SSL_new(c->opt->ctx);
	if (!c->ssl) {
		sslerror("SSL_new");
		longjmp(c->err, 1);
	}
	SSL_set_ex_data(c->ssl, cli_index, c);	
	if (c->opt->option.client) {
		if (c->opt->session) {
			SSL_set_session(c->ssl, c->opt->session);
		}
		SSL_set_fd(c->ssl, c->remote_fd.fd);
		SSL_set_connect_state(c->ssl);
	} else {
		if (c->local_rfd.fd == c->local_wfd.fd)
			SSL_set_fd(c->ssl, c->local_rfd.fd);
		else {
			
			SSL_set_rfd(c->ssl, c->local_rfd.fd);
			SSL_set_wfd(c->ssl, c->local_wfd.fd);
		}
		SSL_set_accept_state(c->ssl);
	}

	
	if (c->opt->option.client) {
		c->sock_rfd = &(c->local_rfd);
		c->sock_wfd = &(c->local_wfd);
		c->ssl_rfd = c->ssl_wfd = &(c->remote_fd);
	} else {
		c->sock_rfd = c->sock_wfd = &(c->remote_fd);
		c->ssl_rfd = &(c->local_rfd);
		c->ssl_wfd = &(c->local_wfd);
	}

	while (1) {
		if (c->opt->option.client)
			i = SSL_connect(c->ssl);
		else
			i = SSL_accept(c->ssl);

		err = SSL_get_error(c->ssl, i);
		if (err == SSL_ERROR_NONE)
			break;	
		if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
			s_poll_init(c->fds);
			s_poll_add(c->fds, c->ssl_rfd->fd,
				   err == SSL_ERROR_WANT_READ,
				   err == SSL_ERROR_WANT_WRITE);
			switch (s_poll_wait(c->fds, c->opt->timeout_busy, 0)) {
			case -1:
				sockerror("init_ssl: s_poll_wait");
				longjmp(c->err, 1);
			case 0:
				s_log(LOG_INFO, "init_ssl: s_poll_wait:"
				      " TIMEOUTbusy exceeded: sending reset");
				longjmp(c->err, 1);
			case 1:
				break;	
			default:
				s_log(LOG_ERR,
				      "init_ssl: s_poll_wait: unknown result");
				longjmp(c->err, 1);
			}
			continue;	
		}
		if (err == SSL_ERROR_SYSCALL) {
			switch (get_last_socket_error()) {
			case S_EINTR:
			case S_EWOULDBLOCK:
#if S_EAGAIN!=S_EWOULDBLOCK
			case S_EAGAIN:
#endif
				continue;
			}
		}
		if (c->opt->option.client)
			sslerror("SSL_connect");
		else
			sslerror("SSL_accept");
		longjmp(c->err, 1);
	}
	if (SSL_session_reused(c->ssl)) {
		s_log(LOG_INFO, "SSL %s: previous session reused",
		      c->opt->option.client ? "connected" : "accepted");
	} else {		
		if (c->opt->option.client) {
			s_log(LOG_INFO,
			      "SSL connected: new session negotiated");
			old_session = c->opt->session;
			c->opt->session = SSL_get1_session(c->ssl);	
			if (old_session)
				SSL_SESSION_free(old_session);	
		} else
			s_log(LOG_INFO, "SSL accepted: new session negotiated");
		print_cipher(c);
	}
}
示例#15
0
文件: ssl.c 项目: witchu/lua-openssl
static int openssl_ssl_set(lua_State*L)
{
  SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl");
  int i;
  int top = lua_gettop(L);
  int ret = 1;
  for (i = 2; i <= top; i += 2)
  {
    const char* what = luaL_checklstring(L, i, NULL);
    if (strcmp(what, "fd") == 0)
    {
      ret = SSL_set_fd(s, luaL_checkint(L, i + 1));
    }
    else if (strcmp(what, "rfd") == 0)
    {
      ret = SSL_set_wfd(s, luaL_checkint(L, i + 1));
    }
    else if (strcmp(what, "wfd") == 0)
    {
      ret = SSL_set_wfd(s, luaL_checkint(L, i + 1));
    }
    else if (strcmp(what, "client_CA") == 0)
    {
      X509* x = CHECK_OBJECT(i + 1, X509, "openssl.x509");
      ret = SSL_add_client_CA(s, x);
    }
    else if (strcmp(what, "read_ahead") == 0)
    {
      int yes = auxiliar_checkboolean(L, i + 1);
      SSL_set_read_ahead(s, yes);
    }
    else if (strcmp(what, "cipher_list") == 0)
    {
      const char* list = lua_tostring(L, i + 1);
      ret = SSL_set_cipher_list(s, list);
    }
    else if (strcmp(what, "verify_depth") == 0)
    {
      int depth = luaL_checkint(L, i + 1);
      SSL_set_verify_depth(s, depth);
    }

    else if (strcmp(what, "purpose") == 0)
    {
      //FIX
      int purpose = luaL_checkint(L, i + 1);
      ret = SSL_set_purpose(s, purpose);
    }
    else if (strcmp(what, "trust") == 0)
    {
      //FIX
      int trust = luaL_checkint(L, i + 1);
      ret = SSL_set_trust(s, trust);
    }
    else if (strcmp(what, "verify_result") == 0)
    {
      int result = luaL_checkint(L, i + 1);
      SSL_set_verify_result(s, result);
    }
    else if (strcmp(what, "hostname") == 0)
    {
      const char* hostname = luaL_checkstring(L, i + 1);
      SSL_set_tlsext_host_name(s, hostname);
    }

#if OPENSSL_VERSION_NUMBER > 0x10000000L
    else if (strcmp(what, "state") == 0)
    {
      int l = luaL_checkint(L, 2);
      SSL_set_state(s, l);
    }
#endif
    else
      luaL_argerror(L, i, "don't understand");

    if (ret != 1)
      return openssl_pushresult(L, ret);
  }
  return 0;
}
示例#16
0
int
tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
    const char *servername)
{
	union tls_addr addrbuf;
	int rv = -1;

	if ((ctx->flags & TLS_CLIENT) == 0) {
		tls_set_errorx(ctx, "not a client context");
		goto err;
	}

	if (fd_read < 0 || fd_write < 0) {
		tls_set_errorx(ctx, "invalid file descriptors");
		goto err;
	}

	if (servername != NULL) {
		if ((ctx->servername = strdup(servername)) == NULL) {
			tls_set_errorx(ctx, "out of memory");
			goto err;
		}
	}

	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
		tls_set_errorx(ctx, "ssl context failure");
		goto err;
	}

	if (tls_configure_ssl(ctx) != 0)
		goto err;
	if (tls_configure_keypair(ctx, ctx->ssl_ctx, ctx->config->keypair, 0) != 0)
		goto err;

	if (ctx->config->verify_name) {
		if (servername == NULL) {
			tls_set_errorx(ctx, "server name not specified");
			goto err;
		}
	}

	if (ctx->config->verify_cert &&
	    (tls_configure_ssl_verify(ctx, SSL_VERIFY_PEER) == -1))
		goto err;

	if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_callback) != 1) {
		tls_set_errorx(ctx, "ssl OCSP verification setup failure");
		goto err;
	}

	if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
		tls_set_errorx(ctx, "ssl connection failure");
		goto err;
	}
	if (SSL_set_app_data(ctx->ssl_conn, ctx) != 1) {
		tls_set_errorx(ctx, "ssl application data failure");
		goto err;
	}
	if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 ||
	    SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) {
		tls_set_errorx(ctx, "ssl file descriptor failure");
		goto err;
	}
	if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) {
		tls_set_errorx(ctx, "ssl OCSP extension setup failure");
		goto err;
	}

	/*
	 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
	 * permitted in "HostName".
	 */
	if (servername != NULL &&
	    inet_pton(AF_INET, servername, &addrbuf) != 1 &&
	    inet_pton(AF_INET6, servername, &addrbuf) != 1) {
		if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) {
			tls_set_errorx(ctx, "server name indication failure");
			goto err;
		}
	}

	rv = 0;

 err:
	return (rv);
}
示例#17
0
文件: imap-send.c 项目: Fykec/git
static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int verify)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
	const SSL_METHOD *meth;
#else
	SSL_METHOD *meth;
#endif
	SSL_CTX *ctx;
	int ret;
	X509 *cert;

	SSL_library_init();
	SSL_load_error_strings();

	meth = SSLv23_method();
	if (!meth) {
		ssl_socket_perror("SSLv23_method");
		return -1;
	}

	ctx = SSL_CTX_new(meth);
	if (!ctx) {
		ssl_socket_perror("SSL_CTX_new");
		return -1;
	}

	if (use_tls_only)
		SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

	if (verify)
		SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

	if (!SSL_CTX_set_default_verify_paths(ctx)) {
		ssl_socket_perror("SSL_CTX_set_default_verify_paths");
		return -1;
	}
	sock->ssl = SSL_new(ctx);
	if (!sock->ssl) {
		ssl_socket_perror("SSL_new");
		return -1;
	}
	if (!SSL_set_rfd(sock->ssl, sock->fd[0])) {
		ssl_socket_perror("SSL_set_rfd");
		return -1;
	}
	if (!SSL_set_wfd(sock->ssl, sock->fd[1])) {
		ssl_socket_perror("SSL_set_wfd");
		return -1;
	}

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
	/*
	 * SNI (RFC4366)
	 * OpenSSL does not document this function, but the implementation
	 * returns 1 on success, 0 on failure after calling SSLerr().
	 */
	ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
	if (ret != 1)
		warning("SSL_set_tlsext_host_name(%s) failed.", server.host);
#endif

	ret = SSL_connect(sock->ssl);
	if (ret <= 0) {
		socket_perror("SSL_connect", sock, ret);
		return -1;
	}

	if (verify) {
		/* make sure the hostname matches that of the certificate */
		cert = SSL_get_peer_certificate(sock->ssl);
		if (!cert)
			return error("unable to get peer certificate.");
		if (verify_hostname(cert, server.host) < 0)
			return -1;
	}

	return 0;
}
示例#18
0
static void init_ssl(CLI *c) {
    int i, err;
    SSL_SESSION *old_session;
    int unsafe_openssl;

    c->ssl=SSL_new(c->opt->ctx);
    if(!c->ssl) {
        sslerror("SSL_new");
        longjmp(c->err, 1);
    }
    SSL_set_ex_data(c->ssl, cli_index, c); /* for callbacks */
    if(c->opt->option.client) {
#ifndef OPENSSL_NO_TLSEXT
        if(c->opt->sni) {
            s_log(LOG_DEBUG, "SNI: host name: %s", c->opt->sni);
            if(!SSL_set_tlsext_host_name(c->ssl, c->opt->sni)) {
                sslerror("SSL_set_tlsext_host_name");
                longjmp(c->err, 1);
            }
        }
#endif
        if(c->opt->session) {
            enter_critical_section(CRIT_SESSION);
            SSL_set_session(c->ssl, c->opt->session);
            leave_critical_section(CRIT_SESSION);
        }
        SSL_set_fd(c->ssl, c->remote_fd.fd);
        SSL_set_connect_state(c->ssl);
    } else {
        if(c->local_rfd.fd==c->local_wfd.fd)
            SSL_set_fd(c->ssl, c->local_rfd.fd);
        else {
           /* does it make sense to have SSL on STDIN/STDOUT? */
            SSL_set_rfd(c->ssl, c->local_rfd.fd);
            SSL_set_wfd(c->ssl, c->local_wfd.fd);
        }
        SSL_set_accept_state(c->ssl);
    }

    /* setup some values for transfer() function */
    if(c->opt->option.client) {
        c->sock_rfd=&(c->local_rfd);
        c->sock_wfd=&(c->local_wfd);
        c->ssl_rfd=c->ssl_wfd=&(c->remote_fd);
    } else {
        c->sock_rfd=c->sock_wfd=&(c->remote_fd);
        c->ssl_rfd=&(c->local_rfd);
        c->ssl_wfd=&(c->local_wfd);
    }

    unsafe_openssl=SSLeay()<0x0090810fL ||
        (SSLeay()>=0x10000000L && SSLeay()<0x1000002fL);
    while(1) {
        /* critical section for OpenSSL version < 0.9.8p or 1.x.x < 1.0.0b *
         * this critical section is a crude workaround for CVE-2010-3864   *
         * see http://www.securityfocus.com/bid/44884 for details          *
         * alternative solution is to disable internal session caching     *
         * NOTE: this critical section also covers callbacks (e.g. OCSP)   */
        if(unsafe_openssl)
            enter_critical_section(CRIT_SSL);

        if(c->opt->option.client)
            i=SSL_connect(c->ssl);
        else
            i=SSL_accept(c->ssl);

        if(unsafe_openssl)
            leave_critical_section(CRIT_SSL);

        err=SSL_get_error(c->ssl, i);
        if(err==SSL_ERROR_NONE)
            break; /* ok -> done */
        if(err==SSL_ERROR_WANT_READ || err==SSL_ERROR_WANT_WRITE) {
            s_poll_init(c->fds);
            s_poll_add(c->fds, c->ssl_rfd->fd,
                err==SSL_ERROR_WANT_READ,
                err==SSL_ERROR_WANT_WRITE);
            switch(s_poll_wait(c->fds, c->opt->timeout_busy, 0)) {
            case -1:
                sockerror("init_ssl: s_poll_wait");
                longjmp(c->err, 1);
            case 0:
                s_log(LOG_INFO, "init_ssl: s_poll_wait:"
                    " TIMEOUTbusy exceeded: sending reset");
                longjmp(c->err, 1);
            case 1:
                break; /* OK */
            default:
                s_log(LOG_ERR, "init_ssl: s_poll_wait: unknown result");
                longjmp(c->err, 1);
            }
            continue; /* ok -> retry */
        }
        if(err==SSL_ERROR_SYSCALL) {
            switch(get_last_socket_error()) {
            case S_EINTR:
            case S_EWOULDBLOCK:
#if S_EAGAIN!=S_EWOULDBLOCK
            case S_EAGAIN:
#endif
                continue;
            }
        }
        if(c->opt->option.client)
            sslerror("SSL_connect");
        else
            sslerror("SSL_accept");
        longjmp(c->err, 1);
    }
    if(SSL_session_reused(c->ssl)) {
        s_log(LOG_INFO, "SSL %s: previous session reused",
            c->opt->option.client ? "connected" : "accepted");
    } else { /* a new session was negotiated */
#ifdef USE_WIN32
        win_new_chain(c);
#endif
        if(c->opt->option.client) {
            s_log(LOG_INFO, "SSL connected: new session negotiated");
            enter_critical_section(CRIT_SESSION);
            old_session=c->opt->session;
            c->opt->session=SSL_get1_session(c->ssl); /* store it */
            if(old_session)
                SSL_SESSION_free(old_session); /* release the old one */
            leave_critical_section(CRIT_SESSION);
        } else
            s_log(LOG_INFO, "SSL accepted: new session negotiated");
        print_cipher(c);
    }
}
示例#19
0
int
tls_connect_fds(struct tls *ctx, int fd_read, int fd_write,
    const char *servername)
{
	union { struct in_addr ip4; struct in6_addr ip6; } addrbuf;
	X509 *cert = NULL;
	int ret, err;

	if (ctx->flags & TLS_CONNECTING)
		goto connecting;

	if ((ctx->flags & TLS_CLIENT) == 0) {
		tls_set_error(ctx, "not a client context");
		goto err;
	}

	if (fd_read < 0 || fd_write < 0) {
		tls_set_error(ctx, "invalid file descriptors");
		return (-1);
	}

	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
		tls_set_error(ctx, "ssl context failure");
		goto err;
	}

	if (tls_configure_ssl(ctx) != 0)
		goto err;

	if (ctx->config->verify_name) {
		if (servername == NULL) {
			tls_set_error(ctx, "server name not specified");
			goto err;
		}
	}

	if (ctx->config->verify_cert) {
		SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);

		if (ctx->config->ca_mem != NULL) {
			if (ctx->config->ca_len > INT_MAX) {
				tls_set_error(ctx, "ca too long");
				goto err;
			}

			if (SSL_CTX_load_verify_mem(ctx->ssl_ctx,
			    ctx->config->ca_mem, ctx->config->ca_len) != 1) {
				tls_set_error(ctx,
				    "ssl verify memory setup failure");
				goto err;
			}
		} else if (SSL_CTX_load_verify_locations(ctx->ssl_ctx,
		    ctx->config->ca_file, ctx->config->ca_path) != 1) {
			tls_set_error(ctx, "ssl verify setup failure");
			goto err;
		}
		if (ctx->config->verify_depth >= 0)
			SSL_CTX_set_verify_depth(ctx->ssl_ctx,
			    ctx->config->verify_depth);
	}

	if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
		tls_set_error(ctx, "ssl connection failure");
		goto err;
	}
	if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 ||
	    SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) {
		tls_set_error(ctx, "ssl file descriptor failure");
		goto err;
	}

	/*
	 * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not
	 * permitted in "HostName".
	 */
	if (servername != NULL &&
	    inet_pton(AF_INET, servername, &addrbuf) != 1 &&
	    inet_pton(AF_INET6, servername, &addrbuf) != 1) {
		if (SSL_set_tlsext_host_name(ctx->ssl_conn, servername) == 0) {
			tls_set_error(ctx, "server name indication failure");
			goto err;
		}
	}

 connecting:
	if ((ret = SSL_connect(ctx->ssl_conn)) != 1) {
		err = tls_ssl_error(ctx, ret, "connect");
		if (err == TLS_READ_AGAIN || err == TLS_WRITE_AGAIN) {
			ctx->flags |= TLS_CONNECTING;
			return (err);
		}
		goto err;
	}
	ctx->flags &= ~TLS_CONNECTING;

	if (ctx->config->verify_name) {
		cert = SSL_get_peer_certificate(ctx->ssl_conn);
		if (cert == NULL) {
			tls_set_error(ctx, "no server certificate");
			goto err;
		}
		if ((ret = tls_check_servername(ctx, cert, servername)) != 0) {
			if (ret != -2)
				tls_set_error(ctx, "name `%s' not present in"
				    " server certificate", servername);
			goto err;
		}
	}

	return (0);

err:
	X509_free(cert);

	return (-1);
}
示例#20
0
static int init_ssl(CLI *c) {
    int i, err;

    if(!(c->ssl=SSL_new(ctx))) {
        sslerror("SSL_new");
        return -1;
    }
#if SSLEAY_VERSION_NUMBER >= 0x0922
    SSL_set_session_id_context(c->ssl, sid_ctx, strlen(sid_ctx));
#endif
    if(options.option.client) {
        /* Attempt to use the most recent id in the session cache */
#ifndef HAVE_YASSL /* yassl add, ctx members available */
        if(ctx->session_cache_head)
            if(!SSL_set_session(c->ssl, ctx->session_cache_head))
                log(LOG_WARNING, "Cannot set SSL session id to most recent used");
#endif /* yassl end add */
        SSL_set_fd(c->ssl, c->remote_fd.fd);
        SSL_set_connect_state(c->ssl);
    } else {
        if(c->local_rfd.fd==c->local_wfd.fd)
            SSL_set_fd(c->ssl, c->local_rfd.fd);
        else {
           /* Does it make sence to have SSL on STDIN/STDOUT? */
            SSL_set_rfd(c->ssl, c->local_rfd.fd);
            SSL_set_wfd(c->ssl, c->local_wfd.fd);
        }
        SSL_set_accept_state(c->ssl);
    }

    /* Setup some values for transfer() function */
    if(options.option.client) {
        c->sock_rfd=&(c->local_rfd);
        c->sock_wfd=&(c->local_wfd);
        c->ssl_rfd=c->ssl_wfd=&(c->remote_fd);
    } else {
        c->sock_rfd=c->sock_wfd=&(c->remote_fd);
        c->ssl_rfd=&(c->local_rfd);
        c->ssl_wfd=&(c->local_wfd);
    }

    while(1) {
        if(options.option.client)
            i=SSL_connect(c->ssl);
        else
            i=SSL_accept(c->ssl);
        err=SSL_get_error(c->ssl, i);
        if(err==SSL_ERROR_NONE)
            break; /* ok -> done */
        if(err==SSL_ERROR_WANT_READ) {
            if(waitforsocket(c->ssl_rfd->fd, 0, c->opt->timeout_busy)==1)
                continue; /* ok -> retry */
            return -1; /* timeout or error */
        }
        if(err==SSL_ERROR_WANT_WRITE) {
            if(waitforsocket(c->ssl_wfd->fd, 1, c->opt->timeout_busy)==1)
                continue; /* ok -> retry */
            return -1; /* timeout or error */
        }
        if(err==SSL_ERROR_SYSCALL) {
            switch(get_last_socket_error()) {
            case EINTR:
            case EAGAIN:
                continue; 
            }
        }
        if(options.option.client)
            sslerror("SSL_connect");
        else
            sslerror("SSL_accept");
        return -1;
    }
    print_cipher(c);
    return 0; /* OK */
}