sesser Thu Oct 3 07:33:06 2002 EDT Modified files: /php4/ext/ftp ftp.c ftp.h php_ftp.c php_ftp.h Log: Added ftp_ssl_connect() for FTP over SSL.
Index: php4/ext/ftp/ftp.c diff -u php4/ext/ftp/ftp.c:1.64 php4/ext/ftp/ftp.c:1.65 --- php4/ext/ftp/ftp.c:1.64 Thu Oct 3 05:10:23 2002 +++ php4/ext/ftp/ftp.c Thu Oct 3 07:33:05 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: ftp.c,v 1.64 2002/10/03 09:10:23 sesser Exp $ */ +/* $Id: ftp.c,v 1.65 2002/10/03 11:33:05 sesser Exp $ */ #include "php.h" @@ -98,7 +98,7 @@ static databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp); /* closes the data connection, returns NULL */ -static databuf_t* data_close(databuf_t *data); +static databuf_t* data_close(ftpbuf_t *ftp, databuf_t *data); /* generic file lister */ static char** ftp_genlist(ftpbuf_t *ftp, @@ -168,10 +168,16 @@ { if (ftp == NULL) return NULL; - if (ftp->fd != -1) - closesocket(ftp->fd); if (ftp->data) - data_close(ftp->data); + data_close(ftp, ftp->data); + if (ftp->fd != -1) { +#if HAVE_OPENSSL_EXT + if (ftp->ssl_active) { + SSL_shutdown(ftp->ssl_handle); + } +#endif + closesocket(ftp->fd); + } ftp_gc(ftp); free(ftp); return NULL; @@ -218,9 +224,80 @@ int ftp_login(ftpbuf_t *ftp, const char *user, const char *pass) { +#if HAVE_OPENSSL_EXT + SSL_CTX *ctx = NULL; +#endif if (ftp == NULL) return 0; +#if HAVE_OPENSSL_EXT + if (ftp->use_ssl && !ftp->ssl_active) { + if (!ftp_putcmd(ftp, "AUTH", "TLS")) + return 0; + if (!ftp_getresp(ftp)) + return 0; + + if (ftp->resp != 234) { + if (!ftp_putcmd(ftp, "AUTH", "SSL")) + return 0; + if (!ftp_getresp(ftp)) + return 0; + + if (ftp->resp != 334) { + ftp->use_ssl = 0; + } else { + ftp->old_ssl = 1; + ftp->use_ssl_for_data = 1; + } + } + + /* now enable ssl if we still need to */ + if (ftp->use_ssl) { + ctx = SSL_CTX_new(SSLv23_client_method()); + if (ctx == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, +"ftp_login: failed to create the SSL context"); + return 0; + } + + ftp->ssl_handle = SSL_new(ctx); + if (ftp->ssl_handle == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, +"ftp_login: failed to create the SSL handle"); + SSL_CTX_free(ctx); + return 0; + } + + SSL_set_fd(ftp->ssl_handle, ftp->fd); + + if (SSL_connect(ftp->ssl_handle) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, +"ftp_login: SSL/TLS handshake failed"); + SSL_shutdown(ftp->ssl_handle); + return 0; + } + + ftp->ssl_active = 1; + + if (!ftp->old_ssl) { + + /* set protection buffersize to zero */ + if (!ftp_putcmd(ftp, "PBSZ", "0")) + return 0; + if (!ftp_getresp(ftp)) + return 0; + + /* enable data conn encryption */ + if (!ftp_putcmd(ftp, "PROT", "P")) + 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", user)) return 0; if (!ftp_getresp(ftp)) @@ -585,6 +662,8 @@ if ((data = ftp_getdata(ftp)) == NULL) { goto bail; } + + ftp->data = data; if (resumepos>0) { sprintf(arg, "%u", resumepos); @@ -631,7 +710,8 @@ if (type == FTPTYPE_ASCII && lastch == '\r') php_stream_putc(outstream, '\r'); - data = data_close(data); + data = data_close(ftp, data); + ftp->data = NULL; if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) { goto bail; @@ -639,7 +719,8 @@ return 1; bail: - data_close(data); + data_close(ftp, data); + ftp->data = NULL; return 0; } /* }}} */ @@ -664,6 +745,8 @@ if ((data = ftp_getdata(ftp)) == NULL) goto bail; + + ftp->data = data; if (startpos>0) { sprintf(arg, "%u", startpos); @@ -706,14 +789,14 @@ if (size && my_send(ftp, data->fd, data->buf, size) != size) goto bail; - data = data_close(data); + data = data_close(ftp, data); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) goto bail; return 1; bail: - data_close(data); + data_close(ftp, data); return 0; } /* }}} */ @@ -997,6 +1080,14 @@ return -1; } +#if HAVE_OPENSSL_EXT + if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) { + sent = SSL_write(ftp->ssl_handle, buf, size); + } else + if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && +ftp->data->ssl_active) { + sent = SSL_write(ftp->data->ssl_handle, buf, size); + } else +#endif sent = send(s, buf, size, 0); if (sent == -1) return -1; @@ -1016,7 +1107,7 @@ { fd_set read_set; struct timeval tv; - int n; + int n, nr_bytes; tv.tv_sec = ftp->timeout_sec; tv.tv_usec = 0; @@ -1033,7 +1124,17 @@ return -1; } - return recv(s, buf, len, 0); +#if HAVE_OPENSSL_EXT + if (ftp->use_ssl && ftp->fd == s && ftp->ssl_active) { + nr_bytes = SSL_read(ftp->ssl_handle, buf, len); + } else + if (ftp->use_ssl && ftp->fd != s && ftp->use_ssl_for_data && +ftp->data->ssl_active) { + nr_bytes = SSL_read(ftp->data->ssl_handle, buf, len); + } else +#endif + nr_bytes = recv(s, buf, len, 0); + + return (nr_bytes); } /* }}} */ @@ -1170,6 +1271,7 @@ data->fd = fd; + ftp->data = data; return data; } @@ -1211,6 +1313,7 @@ if (!ftp_getresp(ftp) || ftp->resp != 200) goto bail; + ftp->data = data; return data; } #endif @@ -1227,6 +1330,7 @@ if (!ftp_getresp(ftp) || ftp->resp != 200) goto bail; + ftp->data = data; return data; bail: @@ -1242,11 +1346,14 @@ databuf_t* data_accept(databuf_t *data, ftpbuf_t *ftp) { +#if HAVE_OPENSSL_EXT + SSL_CTX *ctx; +#endif php_sockaddr_storage addr; int size; if (data->fd != -1) - return data; + goto data_accepted; size = sizeof(addr); data->fd = my_accept(ftp, data->listener, (struct sockaddr*) &addr, &size); @@ -1258,6 +1365,42 @@ return NULL; } +data_accepted: +#if HAVE_OPENSSL_EXT + + /* 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 TSRMLS_CC, E_WARNING, "data_accept: +failed to create the SSL context"); + return 0; + } + + data->ssl_handle = SSL_new(ctx); + if (data->ssl_handle == NULL) { + php_error_docref(NULL TSRMLS_CC, 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); + } + + if (SSL_connect(data->ssl_handle) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: +SSL/TLS handshake failed"); + SSL_shutdown(data->ssl_handle); + return 0; + } + + data->ssl_active = 1; + } + +#endif + return data; } /* }}} */ @@ -1265,14 +1408,31 @@ /* {{{ data_close */ databuf_t* -data_close(databuf_t *data) +data_close(ftpbuf_t *ftp, databuf_t *data) { if (data == NULL) return NULL; - if (data->listener != -1) + if (data->listener != -1) { +#if HAVE_OPENSSL_EXT + if (data->ssl_active) { + SSL_shutdown(data->ssl_handle); + data->ssl_active = 0; + } +#endif closesocket(data->listener); - if (data->fd != -1) + } + if (data->fd != -1) { +#if HAVE_OPENSSL_EXT + if (data->ssl_active) { + SSL_shutdown(data->ssl_handle); + data->ssl_active = 0; + } +#endif closesocket(data->fd); + } + if (ftp) { + ftp->data = NULL; + } free(data); return NULL; } @@ -1302,6 +1462,7 @@ if ((data = ftp_getdata(ftp)) == NULL) goto bail; + ftp->data = data; if (!ftp_putcmd(ftp, cmd, path)) goto bail; @@ -1331,7 +1492,7 @@ } } - data = data_close(data); + data = data_close(ftp, data); if (ferror(tmpfp)) goto bail; @@ -1374,7 +1535,7 @@ return ret; bail: - data_close(data); + data_close(ftp, data); fclose(tmpfp); free(ret); return NULL; @@ -1430,7 +1591,7 @@ return (ftp_nb_continue_read(ftp)); bail: - data_close(data); + data_close(ftp, data); return PHP_FTP_FAILED; } /* }}} */ @@ -1483,7 +1644,7 @@ if (type == FTPTYPE_ASCII && lastch == '\r') php_stream_putc(ftp->stream, '\r'); - data = data_close(data); + data = data_close(ftp, data); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) { goto bail; @@ -1493,7 +1654,7 @@ return PHP_FTP_FINISHED; bail: ftp->nb = 0; - data_close(data); + data_close(ftp, data); return PHP_FTP_FAILED; } /* }}} */ @@ -1542,7 +1703,7 @@ return (ftp_nb_continue_write(ftp)); bail: - data_close(data); + data_close(ftp, data); return PHP_FTP_FAILED; } @@ -1589,7 +1750,7 @@ if (size && my_send(ftp, ftp->data->fd, ftp->data->buf, size) != size) goto bail; - ftp->data = data_close(ftp->data); + ftp->data = data_close(ftp, ftp->data); if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) goto bail; @@ -1597,7 +1758,7 @@ ftp->nb = 0; return PHP_FTP_FINISHED; bail: - data_close(ftp->data); + data_close(ftp, ftp->data); ftp->nb = 0; return PHP_FTP_FAILED; } Index: php4/ext/ftp/ftp.h diff -u php4/ext/ftp/ftp.h:1.28 php4/ext/ftp/ftp.h:1.29 --- php4/ext/ftp/ftp.h:1.28 Thu Oct 3 05:10:24 2002 +++ php4/ext/ftp/ftp.h Thu Oct 3 07:33:05 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: ftp.h,v 1.28 2002/10/03 09:10:24 sesser Exp $ */ +/* $Id: ftp.h,v 1.29 2002/10/03 11:33:05 sesser Exp $ */ #ifndef FTP_H #define FTP_H @@ -49,6 +49,8 @@ int fd; /* data connection */ ftptype_t type; /* transfer type */ char buf[FTP_BUFSIZE]; /* data buffer */ + SSL *ssl_handle; /* ssl handle */ + int ssl_active; /* flag if ssl is active or not */ } databuf_t; typedef struct ftpbuf @@ -74,6 +76,14 @@ int lastch; /* last char of previous call */ int direction; /* recv = 0 / send = 1 */ int closestream;/* close or not close stream */ +#if HAVE_OPENSSL_EXT + int use_ssl; /* enable(1) or disable(0) ssl */ + int use_ssl_for_data; /* en/disable ssl for the +dataconnection */ + int old_ssl; /* old mode = forced data +encryption */ + SSL *ssl_handle; /* handle for control +connection */ + int ssl_active; /* ssl active on +control conn */ +#endif + } ftpbuf_t; Index: php4/ext/ftp/php_ftp.c diff -u php4/ext/ftp/php_ftp.c:1.73 php4/ext/ftp/php_ftp.c:1.74 --- php4/ext/ftp/php_ftp.c:1.73 Thu Oct 3 05:10:24 2002 +++ php4/ext/ftp/php_ftp.c Thu Oct 3 07:33:05 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_ftp.c,v 1.73 2002/10/03 09:10:24 sesser Exp $ */ +/* $Id: php_ftp.c,v 1.74 2002/10/03 11:33:05 sesser Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -48,6 +48,9 @@ function_entry php_ftp_functions[] = { PHP_FE(ftp_connect, NULL) +#if HAVE_OPENSSL_EXT + PHP_FE(ftp_ssl_connect, NULL) +#endif PHP_FE(ftp_login, NULL) PHP_FE(ftp_pwd, NULL) PHP_FE(ftp_cdup, NULL) @@ -162,10 +165,49 @@ /* autoseek for resuming */ ftp->autoseek = FTP_DEFAULT_AUTOSEEK; +#if HAVE_OPENSSL_EXT + /* disable ssl */ + ftp->use_ssl = 0; +#endif + + ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf); +} +/* }}} */ + +#if HAVE_OPENSSL_EXT +/* {{{ proto resource ftp_ssl_connect(string host [, int port [, int timeout)]]) + Opens a FTP-SSL stream */ +PHP_FUNCTION(ftp_ssl_connect) +{ + ftpbuf_t *ftp; + char *host; + int host_len, port = 0; + long timeout_sec = FTP_DEFAULT_TIMEOUT; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, +&port, &timeout_sec) == FAILURE) { + return; + } + + if (timeout_sec <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timeout has to be greater +than 0"); + RETURN_FALSE; + } + + /* connect */ + ftp = ftp_open(host, (short)port, timeout_sec TSRMLS_CC); + if (ftp == NULL) { + RETURN_FALSE; + } + + /* autoseek for resuming */ + ftp->autoseek = FTP_DEFAULT_AUTOSEEK; + /* enable ssl */ + ftp->use_ssl = 1; ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf); } /* }}} */ +#endif /* {{{ proto bool ftp_login(resource stream, string username, string password) Logs into the FTP server */ Index: php4/ext/ftp/php_ftp.h diff -u php4/ext/ftp/php_ftp.h:1.20 php4/ext/ftp/php_ftp.h:1.21 --- php4/ext/ftp/php_ftp.h:1.20 Thu Oct 3 05:10:24 2002 +++ php4/ext/ftp/php_ftp.h Thu Oct 3 07:33:05 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_ftp.h,v 1.20 2002/10/03 09:10:24 sesser Exp $ */ +/* $Id: php_ftp.h,v 1.21 2002/10/03 11:33:05 sesser Exp $ */ #ifndef _INCLUDED_FTP_H #define _INCLUDED_FTP_H @@ -35,6 +35,9 @@ PHP_MINFO_FUNCTION(ftp); PHP_FUNCTION(ftp_connect); +#if HAVE_OPENSSL_EXT +PHP_FUNCTION(ftp_ssl_connect); +#endif PHP_FUNCTION(ftp_login); PHP_FUNCTION(ftp_pwd); PHP_FUNCTION(ftp_cdup);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php