diff -urw php-4.0.1pl2-orig/ext/standard/config.m4 php-4.0.1pl2/ext/standard/config.m4 --- php-4.0.1pl2-orig/ext/standard/config.m4 Tue May 23 09:09:11 2000 +++ php-4.0.1pl2/ext/standard/config.m4 Tue Aug 22 12:40:12 2000 @@ -146,5 +146,34 @@ fi ]) +PHP_ARG_WITH(ssl, for ssl support, +[ --with-ssl[=DIR] Include ssl support]) +AC_DEFUN(PHP_SSL_SETUP_OPENSSL,[ + for i in /usr/local/ssl /usr/local /usr /usr/local/openssl $PHP_OPENSSL; do + if test -r $i/include/openssl/evp.h; then + OPENSSL_DIR=$i + OPENSSL_INC=$i/include/openssl + elif test -r $i/include/evp.h; then + OPENSSL_DIR=$i + OPENSSL_INC=$i/include + fi + done + + if test -z "$OPENSSL_DIR"; then + AC_MSG_ERROR(Cannot find OpenSSL's ) + fi + + AC_ADD_LIBPATH($OPENSSL_DIR/lib, SSL_SHARED_LIBADD) + AC_ADD_LIBRARY(ssl, yes, SSL_SHARED_LIBADD) + AC_ADD_LIBRARY(crypto, yes, SSL_SHARED_LIBADD) + AC_ADD_INCLUDE($OPENSSL_INC) +]) + + +if test "$PHP_SSL" != "no"; then + PHP_SSL_SETUP_OPENSSL + AC_DEFINE(HAVE_SSL, 1, [ ]) +fi + PHP_EXTENSION(standard) diff -urw php-4.0.1pl2-orig/ext/standard/file.c php-4.0.1pl2/ext/standard/file.c --- php-4.0.1pl2-orig/ext/standard/file.c Tue Jun 27 09:55:52 2000 +++ php-4.0.1pl2/ext/standard/file.c Tue Aug 22 13:43:08 2000 @@ -1210,7 +1210,12 @@ } if (issock){ + /* FIXME: if anyone decides to use this macro to write to SSL sockets, it will fall over */ +#if HAVE_SSL + ret = php_sock_ssl_send((*arg2)->value.str.val,num_bytes,socketd); +#else ret = SOCK_WRITEL((*arg2)->value.str.val,num_bytes,socketd); +#endif } else { ret = fwrite((*arg2)->value.str.val,1,num_bytes,(FILE*)what); } diff -urw php-4.0.1pl2-orig/ext/standard/fsock.c php-4.0.1pl2/ext/standard/fsock.c --- php-4.0.1pl2-orig/ext/standard/fsock.c Mon Jun 19 09:02:48 2000 +++ php-4.0.1pl2/ext/standard/fsock.c Tue Aug 22 16:25:08 2000 @@ -200,6 +200,10 @@ #endif } /* }}} */ + + +static php_sockbuf *php_sockcreate(int socket FLS_DC); + /* {{{ php_fsockopen() */ /* @@ -214,6 +218,7 @@ int arg_count=ZEND_NUM_ARGS(); int socketd = -1; unsigned char udp = 0; + unsigned char use_ssl = 0; /* 1 = SSLv2/SSLv3, 2 = TLSv1 */ struct timeval timeout = { 60, 0 }; unsigned short portno; unsigned long conv; @@ -267,6 +272,24 @@ (*args[0])->value.str.val[5] == '/') { udp = 1; } +#if HAVE_SSL + else if((*args[0])->value.str.val[0] == 's' && + (*args[0])->value.str.val[1] == 's' && + (*args[0])->value.str.val[2] == 'l' && + (*args[0])->value.str.val[3] == ':' && + (*args[0])->value.str.val[4] == '/' && + (*args[0])->value.str.val[5] == '/') { + use_ssl = 1; + } + else if((*args[0])->value.str.val[0] == 't' && + (*args[0])->value.str.val[1] == 'l' && + (*args[0])->value.str.val[2] == 's' && + (*args[0])->value.str.val[3] == ':' && + (*args[0])->value.str.val[4] == '/' && + (*args[0])->value.str.val[5] == '/') { + use_ssl = 2; + } +#endif socketd = socket(AF_INET,udp ? SOCK_DGRAM : SOCK_STREAM,0); @@ -277,7 +300,7 @@ server.sin_family = AF_INET; - if(lookup_hostname(udp ? &(*args[0])->value.str.val[6] : (*args[0])->value.str.val,&server.sin_addr)) { + if(lookup_hostname((use_ssl | udp) ? &(*args[0])->value.str.val[6] : (*args[0])->value.str.val,&server.sin_addr)) { CLOSE_SOCK(1); RETURN_FALSE; } @@ -335,6 +358,54 @@ #endif #endif +#if HAVE_SSL + if (use_ssl) { + /* we need to create sockbuf now so we can remember that we are using SSL */ + php_sockbuf * sbuf = php_sockcreate(socketd FLS_CC); + if (sbuf) { + /* now fire up an SSL client context */ + SSL_METHOD * meth; + SSL_CTX * ctx; + SSL * ssl; + int sslret; + + meth = use_ssl == 1 ? SSLv23_client_method() : TLSv1_client_method(); + ctx = SSL_CTX_new(meth); + ssl = SSL_new(ctx); + sbuf->ssl = ssl; + + SSL_set_fd(sbuf->ssl, socketd); + + sslret = SSL_connect(ssl); + + if (sslret < 0) { + if(arg_count>2) (*args[2])->value.lval = SSL_get_error(sbuf->ssl, sslret); + if(arg_count>3) { + char buf[1024]; + ERR_error_string((*args[2])->value.lval, buf); + (*args[3])->value.str.val = estrdup(buf); + (*args[3])->value.str.len = strlen((*args[3])->value.str.val); + } + + CLOSE_SOCK(1); + RETURN_FALSE; + } + /* success - fall through to below */ + } + else { + if(arg_count>2) (*args[2])->value.lval = ENOMEM; + if(arg_count>3) { + (*args[3])->value.str.val = estrdup("failed to create socket buffer"); + (*args[3])->value.str.len = strlen((*args[3])->value.str.val); + } + CLOSE_SOCK(1); + + RETURN_FALSE; + } + } + +#endif + *sock=socketd; if (persistent) { zend_hash_update(&FG(ht_fsock_keys), key, strlen(key) + 1, @@ -366,12 +437,27 @@ #define CHUNK_SIZE 8192 #define SOCK_DESTROY(sock) \ if(sock->readbuf) pefree(sock->readbuf, sock->persistent); \ + if(sock->ssl) php_ssl_cleanup_sockbuf(sock); \ if(sock->prev) sock->prev->next = sock->next; \ if(sock->next) sock->next->prev = sock->prev; \ if(sock == FG(phpsockbuf)) \ FG(phpsockbuf) = sock->next; \ pefree(sock, sock->persistent) +#if HAVE_SSL +static void php_ssl_cleanup_sockbuf(struct php_sockbuf * sock) +{ + SSL_CTX * ctx; + if (sock->ssl) { + SSL_shutdown(sock->ssl); + ctx = sock->ssl->ctx; + SSL_free(sock->ssl); + sock->ssl = NULL; + SSL_CTX_free(ctx); + } +} +#endif + static void php_cleanup_sockbuf(int persistent FLS_DC) { php_sockbuf *now, *next; @@ -419,6 +505,7 @@ sock->is_blocked = 1; sock->chunk_size = FG(def_chunk_size); sock->timeout.tv_sec = -1; + sock->ssl = NULL; FG(phpsockbuf) = sock; return sock; @@ -479,10 +566,18 @@ sock = php_sockfind(socket FLS_CC); if(sock) { if(!sock->persistent) { +#if HAVE_SSL + if (sock->ssl) + php_ssl_cleanup_sockbuf(sock); +#endif SOCK_CLOSE(sock->socket); SOCK_DESTROY(sock); } } else { +#if HAVE_SSL + if (sock->ssl) + php_ssl_cleanup_sockbuf(sock); +#endif SOCK_CLOSE(socket); } @@ -541,6 +636,11 @@ } /* read at a maximum sock->chunk_size */ +#if HAVE_SSL + if (sock->ssl) + nr_bytes = SSL_read(sock->ssl, buf, sock->chunk_size); + else +#endif nr_bytes = recv(sock->socket, buf, sock->chunk_size, 0); if(nr_bytes > 0) { if(sock->writepos + nr_bytes > sock->readbuflen) { @@ -603,6 +703,20 @@ SOCK_FIND(sock, socket); \ if(sock->is_blocked) php_sockread_total(sock, max); else php_sockread(sock) + +#if HAVE_SSL +/* {{{ php_sock_ssl_send + send to a socket that uses SSL +*/ +int php_sock_ssl_send(char * buf, size_t len, int socket) +{ + SOCK_FIND(sock, socket); + if (sock->ssl) + return SSL_write(sock->ssl, buf, len); + return SOCK_WRITEL(buf, len, socket); +} +#endif + /* {{{ php_sock_fgets() */ /* * FIXME: fgets depends on '\n' as line delimiter @@ -738,6 +852,11 @@ PHP_MINIT_FUNCTION(fsock) { +#if HAVE_SSL + SSL_library_init(); + SSL_load_error_strings(); +#endif + #ifdef ZTS fsock_globals_id = ts_allocate_id(sizeof(php_fsock_globals), (ts_allocate_ctor) fsock_globals_ctor, (ts_allocate_dtor) fsock_globals_dtor); #else diff -urw php-4.0.1pl2-orig/ext/standard/fsock.h php-4.0.1pl2/ext/standard/fsock.h --- php-4.0.1pl2-orig/ext/standard/fsock.h Mon Mar 6 20:37:11 2000 +++ php-4.0.1pl2/ext/standard/fsock.h Tue Aug 22 13:43:38 2000 @@ -55,6 +55,12 @@ #include #endif +#if HAVE_SSL +#include +#include +#include +#endif + struct php_sockbuf { int socket; unsigned char *readbuf; @@ -69,6 +75,11 @@ size_t chunk_size; struct timeval timeout; char timeout_event; +#if HAVE_SSL + SSL * ssl; +#else + void * ssl; +#endif }; typedef struct php_sockbuf php_sockbuf; @@ -88,6 +99,9 @@ int php_sock_close(int socket); size_t php_sock_set_def_chunk_size(size_t size); void php_msock_destroy(int *data); +#if HAVE_SSL +int php_sock_ssl_send(char * buf, size_t len, int socket); +#endif PHPAPI int connect_nonb(int sockfd, struct sockaddr *addr, socklen_t addrlen, struct timeval *timeout); PHPAPI struct php_sockbuf *php_get_socket(int socket); diff -urw php-4.0.1pl2-orig/php_config.h.in php-4.0.1pl2/php_config.h.in --- php-4.0.1pl2-orig/php_config.h.in Wed Jun 28 18:37:34 2000 +++ php-4.0.1pl2/php_config.h.in Tue Aug 22 13:18:08 2000 @@ -1409,6 +1409,9 @@ /* Whether the system supports BlowFish salt */ #undef PHP_BLOWFISH_CRYPT +/* */ +#undef HAVE_SSL + /* Whether to build standard as dynamic module */ #undef COMPILE_DL_STANDARD