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

Reply via email to