Exemplo n.º 1
0
/* {{{ ftp_login
 */
int
ftp_login(ftpbuf_t *ftp, const char *user, const size_t user_len, const char *pass, const size_t pass_len)
{
#ifdef HAVE_FTP_SSL
	SSL_CTX	*ctx = NULL;
	long ssl_ctx_options = SSL_OP_ALL;
	int err, res;
	zend_bool retry;
#endif
	if (ftp == NULL) {
		return 0;
	}

#ifdef HAVE_FTP_SSL
	if (ftp->use_ssl && !ftp->ssl_active) {
		if (!ftp_putcmd(ftp, "AUTH", sizeof("AUTH")-1, "TLS", sizeof("TLS")-1)) {
			return 0;
		}
		if (!ftp_getresp(ftp)) {
			return 0;
		}

		if (ftp->resp != 234) {
			if (!ftp_putcmd(ftp, "AUTH", sizeof("AUTH")-1, "SSL", sizeof("SSL")-1)) {
				return 0;
			}
			if (!ftp_getresp(ftp)) {
				return 0;
			}

			if (ftp->resp != 334) {
				return 0;
			} else {
				ftp->old_ssl = 1;
				ftp->use_ssl_for_data = 1;
			}
		}

		ctx = SSL_CTX_new(SSLv23_client_method());
		if (ctx == NULL) {
			php_error_docref(NULL, E_WARNING, "failed to create the SSL context");
			return 0;
		}

#if OPENSSL_VERSION_NUMBER >= 0x0090605fL
		ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
		SSL_CTX_set_options(ctx, ssl_ctx_options);

		/* allow SSL to re-use sessions */
		SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_BOTH);

		ftp->ssl_handle = SSL_new(ctx);
		if (ftp->ssl_handle == NULL) {
			php_error_docref(NULL, E_WARNING, "failed to create the SSL handle");
			SSL_CTX_free(ctx);
			return 0;
		}

		SSL_set_fd(ftp->ssl_handle, ftp->fd);

		do {
			res = SSL_connect(ftp->ssl_handle);
			err = SSL_get_error(ftp->ssl_handle, res);

			/* TODO check if handling other error codes would make sense */
			switch (err) {
				case SSL_ERROR_NONE:
					retry = 0;
					break;

				case SSL_ERROR_ZERO_RETURN:
					retry = 0;
					SSL_shutdown(ftp->ssl_handle);
					break;

				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_WRITE: {
						php_pollfd p;
						int i;

						p.fd = ftp->fd;
						p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
						p.revents = 0;

						i = php_poll2(&p, 1, 300);

						retry = i > 0;
					}
					break;

				default:
					php_error_docref(NULL, E_WARNING, "SSL/TLS handshake failed");
					SSL_shutdown(ftp->ssl_handle);
					SSL_free(ftp->ssl_handle);
					return 0;
			}
		} while (retry);

		ftp->ssl_active = 1;

		if (!ftp->old_ssl) {

			/* set protection buffersize to zero */
			if (!ftp_putcmd(ftp, "PBSZ", sizeof("PBSZ")-1, "0", sizeof("0")-1)) {
				return 0;
			}
			if (!ftp_getresp(ftp)) {
				return 0;
			}

			/* enable data conn encryption */
			if (!ftp_putcmd(ftp, "PROT", sizeof("PROT")-1, "P", sizeof("P")-1)) {
				return 0;
			}
			if (!ftp_getresp(ftp)) {
				return 0;
			}

			ftp->use_ssl_for_data = (ftp->resp >= 200 && ftp->resp <=299);
		}
	}
#endif

	if (!ftp_putcmd(ftp, "USER", sizeof("USER")-1, user, user_len)) {
		return 0;
	}
	if (!ftp_getresp(ftp)) {
		return 0;
	}
	if (ftp->resp == 230) {
		return 1;
	}
	if (ftp->resp != 331) {
		return 0;
	}
	if (!ftp_putcmd(ftp, "PASS", sizeof("PASS")-1, pass, pass_len)) {
		return 0;
	}
	if (!ftp_getresp(ftp)) {
		return 0;
	}
	return (ftp->resp == 230);
}
Exemplo n.º 2
0
/* {{{ data_accept
 */
databuf_t*
data_accept(databuf_t *data, ftpbuf_t *ftp)
{
	php_sockaddr_storage addr;
	socklen_t			size;

#ifdef HAVE_FTP_SSL
	SSL_CTX		*ctx;
	SSL_SESSION *session;
	int err, res;
	zend_bool retry;
#endif

	if (data->fd != -1) {
		goto data_accepted;
	}
	size = sizeof(addr);
	data->fd = my_accept(ftp, data->listener, (struct sockaddr*) &addr, &size);
	closesocket(data->listener);
	data->listener = -1;

	if (data->fd == -1) {
		efree(data);
		return NULL;
	}

data_accepted:
#ifdef HAVE_FTP_SSL

	/* now enable ssl if we need to */
	if (ftp->use_ssl && ftp->use_ssl_for_data) {
		ctx = SSL_get_SSL_CTX(ftp->ssl_handle);
		if (ctx == NULL) {
			php_error_docref(NULL, E_WARNING, "data_accept: failed to retreive the existing SSL context");
			return 0;
		}

		data->ssl_handle = SSL_new(ctx);
		if (data->ssl_handle == NULL) {
			php_error_docref(NULL, E_WARNING, "data_accept: failed to create the SSL handle");
			return 0;
		}

		SSL_set_fd(data->ssl_handle, data->fd);

		if (ftp->old_ssl) {
			SSL_copy_session_id(data->ssl_handle, ftp->ssl_handle);
		}

		/* get the session from the control connection so we can re-use it */
		session = SSL_get_session(ftp->ssl_handle);
		if (session == NULL) {
			php_error_docref(NULL, E_WARNING, "data_accept: failed to retreive the existing SSL session");
			SSL_free(data->ssl_handle);
			return 0;
		}

		/* and set it on the data connection */
		res = SSL_set_session(data->ssl_handle, session);
		if (res == 0) {
			php_error_docref(NULL, E_WARNING, "data_accept: failed to set the existing SSL session");
			SSL_free(data->ssl_handle);
			return 0;
		}

		do {
			res = SSL_connect(data->ssl_handle);
			err = SSL_get_error(data->ssl_handle, res);

			switch (err) {
				case SSL_ERROR_NONE:
					retry = 0;
					break;

				case SSL_ERROR_ZERO_RETURN:
					retry = 0;
					SSL_shutdown(data->ssl_handle);
					break;

				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_WRITE: {
						php_pollfd p;
						int i;

						p.fd = ftp->fd;
						p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
						p.revents = 0;

						i = php_poll2(&p, 1, 300);

						retry = i > 0;
					}
					break;

				default:
					php_error_docref(NULL, E_WARNING, "data_accept: SSL/TLS handshake failed");
					SSL_shutdown(data->ssl_handle);
					SSL_free(data->ssl_handle);
					return 0;
			}
		} while (retry);

		data->ssl_active = 1;
	}

#endif

	return data;
}
Exemplo n.º 3
0
/* {{{ my_send
 */
int
my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
{
	zend_long		size, sent;
    int         n;
#ifdef HAVE_FTP_SSL
	int err;
	zend_bool retry = 0;
	SSL *handle = NULL;
	php_socket_t fd;
#endif


	size = len;
	while (size) {
		n = php_pollfd_for_ms(s, POLLOUT, ftp->timeout_sec * 1000);

		if (n < 1) {
#ifdef PHP_WIN32
			if (n == 0) {
				_set_errno(ETIMEDOUT);
			}
#else
			if (n == 0) {
				errno = ETIMEDOUT;
			}
#endif
			return -1;
		}

#ifdef HAVE_FTP_SSL
		if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
			handle = ftp->ssl_handle;
			fd = ftp->fd;
		} else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {
			handle = ftp->data->ssl_handle;
			fd = ftp->data->fd;
		}

		if (handle) {
			do {
				sent = SSL_write(handle, buf, size);
				err = SSL_get_error(handle, sent);

				switch (err) {
					case SSL_ERROR_NONE:
						retry = 0;
						break;

					case SSL_ERROR_ZERO_RETURN:
						retry = 0;
						SSL_shutdown(handle);
						break;

					case SSL_ERROR_WANT_READ:
					case SSL_ERROR_WANT_CONNECT: {
							php_pollfd p;
							int i;

							p.fd = fd;
							p.events = POLLOUT;
							p.revents = 0;

							i = php_poll2(&p, 1, 300);

							retry = i > 0;
						}
						break;

					default:
						php_error_docref(NULL, E_WARNING, "SSL write failed");
						return -1;
				}
			} while (retry);
		} else {
#endif
			sent = send(s, buf, size, 0);
#ifdef HAVE_FTP_SSL
		}
#endif
		if (sent == -1) {
			return -1;
		}

		buf = (char*) buf + sent;
		size -= sent;
	}

	return len;
}
Exemplo n.º 4
0
/* {{{ my_recv
 */
int
my_recv(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len)
{
	int		n, nr_bytes;
#ifdef HAVE_FTP_SSL
	int err;
	zend_bool retry = 0;
	SSL *handle = NULL;
	php_socket_t fd;
#endif

	n = php_pollfd_for_ms(s, PHP_POLLREADABLE, ftp->timeout_sec * 1000);
	if (n < 1) {
#ifdef PHP_WIN32
		if (n == 0) {
			_set_errno(ETIMEDOUT);
		}
#else
		if (n == 0) {
			errno = ETIMEDOUT;
		}
#endif
		return -1;
	}

#ifdef HAVE_FTP_SSL
	if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) {
		handle = ftp->ssl_handle;
		fd = ftp->fd;
	} else if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && ftp->data->ssl_active) {
		handle = ftp->data->ssl_handle;
		fd = ftp->data->fd;
	}

	if (handle) {
		do {
			nr_bytes = SSL_read(handle, buf, len);
			err = SSL_get_error(handle, nr_bytes);

			switch (err) {
				case SSL_ERROR_NONE:
					retry = 0;
					break;

				case SSL_ERROR_ZERO_RETURN:
					retry = 0;
					SSL_shutdown(handle);
					break;

				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_CONNECT: {
						php_pollfd p;
						int i;

						p.fd = fd;
						p.events = POLLIN|POLLPRI;
						p.revents = 0;

						i = php_poll2(&p, 1, 300);

						retry = i > 0;
					}
					break;

				default:
					php_error_docref(NULL, E_WARNING, "SSL read failed");
					return -1;
			}
		} while (retry);
	} else {
#endif
		nr_bytes = recv(s, buf, len, 0);
#ifdef HAVE_FTP_SSL
	}
#endif
	return (nr_bytes);
}
Exemplo n.º 5
0
Arquivo: ftp.c Projeto: 20uf/php-src
/* {{{ data_accept
 */
databuf_t*
data_accept(databuf_t *data, ftpbuf_t *ftp)
{
	php_sockaddr_storage addr;
	socklen_t			size;

#ifdef HAVE_FTP_SSL
	SSL_CTX		*ctx;
	zend_long ssl_ctx_options = SSL_OP_ALL;
	int err, res;
	zend_bool retry;
#endif

	if (data->fd != -1) {
		goto data_accepted;
	}
	size = sizeof(addr);
	data->fd = my_accept(ftp, data->listener, (struct sockaddr*) &addr, &size);
	closesocket(data->listener);
	data->listener = -1;

	if (data->fd == -1) {
		efree(data);
		return NULL;
	}

data_accepted:
#ifdef HAVE_FTP_SSL

	/* now enable ssl if we need to */
	if (ftp->use_ssl && ftp->use_ssl_for_data) {
		ctx = SSL_CTX_new(SSLv23_client_method());
		if (ctx == NULL) {
			php_error_docref(NULL, E_WARNING, "data_accept: failed to create the SSL context");
			return 0;
		}

#if OPENSSL_VERSION_NUMBER >= 0x0090605fL
		ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
		SSL_CTX_set_options(ctx, ssl_ctx_options);

		data->ssl_handle = SSL_new(ctx);
		if (data->ssl_handle == NULL) {
			php_error_docref(NULL, E_WARNING, "data_accept: failed to create the SSL handle");
			SSL_CTX_free(ctx);
			return 0;
		}


		SSL_set_fd(data->ssl_handle, data->fd);

		if (ftp->old_ssl) {
			SSL_copy_session_id(data->ssl_handle, ftp->ssl_handle);
		}

		do {
			res = SSL_connect(data->ssl_handle);
			err = SSL_get_error(data->ssl_handle, res);

			switch (err) {
				case SSL_ERROR_NONE:
					retry = 0;
					break;

				case SSL_ERROR_ZERO_RETURN:
					retry = 0;
					SSL_shutdown(data->ssl_handle);
					break;

				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_WRITE: {
						php_pollfd p;
						int i;

						p.fd = ftp->fd;
						p.events = (err == SSL_ERROR_WANT_READ) ? (POLLIN|POLLPRI) : POLLOUT;
						p.revents = 0;

						i = php_poll2(&p, 1, 300);

						retry = i > 0;
					}
					break;

				default:
					php_error_docref(NULL, E_WARNING, "data_accept: SSL/TLS handshake failed");
					SSL_shutdown(data->ssl_handle);
					SSL_free(data->ssl_handle);
					return 0;
			}
		} while (retry);

		data->ssl_active = 1;
	}

#endif

	return data;
}