Mercurial > gftp.yaz
changeset 168:c505d9ba9d53
2003-6-6 Brian Masney <masneyb@gftp.org>
* lib/gftp.h - if USE_SSL is defined, include the OpenSSL headers.
Added read_function, write_function and post_connect function pointers
to gftp_request structure. Added SSL object to gftp_request structure
if USE_SSL is defined. Added protocol number and init function
declarations for the HTTPS protocol
* lib/options.h - added HTTPS to the list of supported protocols
* lib/protocols.c lib/cache.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c -
renamed gftp_read(), gftp_write() and gftp_set_sockblocking() to
gftp_fd_read(), gftp_fd_write() and gftp_fd_set_sockblocking()
respectively
* lib/bookmark.c lib/local.c
* lib/misc.c lib/rfc2068.c - moved base64_encode() to misc.c
* lib/protocols.c - improved parsing of URLs. Rather than calling
gftp_read() or gftp_write() directly, call the read_function or
write_function that is set in the request structure. Expanded tabs
to spaces. Cleanup for parsing of timestamps. In
gftp_connect_server(), if a post_connect function pointer is set,
call it after we are connected to the server. Improvements to
gftp_get_line ().
* lib/httpcommon.h lib/rfc2068.c - moved rfc2068_params structure to
httpcommon.h. Fix for chunked file transfers, they were not handled
at all before. Made the I/O calls a little more generic so that we can
read from either a socket or a SSL connection.
* lib/sslcommon.c - added generic SSL layer
* lib/https.c - added support for the HTTPS protocol. It piggy backs
off of the existing HTTP support and uses the generic SSL layer
* src/gtk/bookmarks.c src/gtk/chmod_dialog.c src/gtk/gftp-gtk.c
src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/options_dialog.c
src/gtk/view_dialog.c - set the window icon name to the gFTP <version>
* configure.in - added lib back to SUBDIRS (oops)
* lib/Makefile.am - added https.c, sslcommon.c and httpcommon.h
author | masneyb |
---|---|
date | Sun, 08 Jun 2003 15:04:40 +0000 |
parents | 4b767a186810 |
children | d40f9db52cdf |
files | ChangeLog lib/Makefile.am lib/bookmark.c lib/cache.c lib/gftp.h lib/httpcommon.h lib/https.c lib/local.c lib/misc.c lib/options.h lib/protocols.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c lib/sslcommon.c src/gtk/bookmarks.c src/gtk/chmod_dialog.c src/gtk/gftp-gtk.c src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/options_dialog.c src/gtk/view_dialog.c |
diffstat | 22 files changed, 994 insertions(+), 307 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed May 28 18:37:28 2003 +0000 +++ b/ChangeLog Sun Jun 08 15:04:40 2003 +0000 @@ -1,13 +1,57 @@ -2003-5-27 Brian Masney <masneyb@gftp.org> - * Makefile.am configure.in autogen.sh - build fixes +2003-6-6 Brian Masney <masneyb@gftp.org> + * lib/gftp.h - if USE_SSL is defined, include the OpenSSL headers. + Added read_function, write_function and post_connect function pointers + to gftp_request structure. Added SSL object to gftp_request structure + if USE_SSL is defined. Added protocol number and init function + declarations for the HTTPS protocol + + * lib/options.h - added HTTPS to the list of supported protocols + + * lib/protocols.c lib/cache.c lib/rfc2068.c lib/rfc959.c lib/sshv2.c - + renamed gftp_read(), gftp_write() and gftp_set_sockblocking() to + gftp_fd_read(), gftp_fd_write() and gftp_fd_set_sockblocking() + respectively + + * lib/bookmark.c lib/local.c + + * lib/misc.c lib/rfc2068.c - moved base64_encode() to misc.c - * src/text/gftp-text.c - if the protocol we are connecting to - doesn't need a username/password, don't prompt the user for one + * lib/protocols.c - improved parsing of URLs. Rather than calling + gftp_read() or gftp_write() directly, call the read_function or + write_function that is set in the request structure. Expanded tabs + to spaces. Cleanup for parsing of timestamps. In + gftp_connect_server(), if a post_connect function pointer is set, + call it after we are connected to the server. Improvements to + gftp_get_line (). + + * lib/httpcommon.h lib/rfc2068.c - moved rfc2068_params structure to + httpcommon.h. Fix for chunked file transfers, they were not handled + at all before. Made the I/O calls a little more generic so that we can + read from either a socket or a SSL connection. + + * lib/sslcommon.c - added generic SSL layer + + * lib/https.c - added support for the HTTPS protocol. It piggy backs + off of the existing HTTP support and uses the generic SSL layer + + * src/gtk/bookmarks.c src/gtk/chmod_dialog.c src/gtk/gftp-gtk.c + src/gtk/menu-items.c src/gtk/misc-gtk.c src/gtk/options_dialog.c + src/gtk/view_dialog.c - set the window icon name to the gFTP <version> + + * configure.in - added lib back to SUBDIRS (oops) + + * lib/Makefile.am - added https.c, sslcommon.c and httpcommon.h + +2003-5-27 Brian Masney <masneyb@gftp.org> + * Makefile.am configure.in autogen.sh - build fixes + + * src/text/gftp-text.c - if the protocol we are connecting to + doesn't need a username/password, don't prompt the user for one 2003-5-22 Brian Masney <masneyb@gftp.org> - * lib/misc.c (gftp_usage) - updated usage statement + * lib/misc.c (gftp_usage) - updated usage statement - * lib/options.h - put terminate options properly + * lib/options.h - put terminate options properly 2003-05-06 Christian Rose <menthos@menthos.com> @@ -837,7 +881,7 @@ * cvsclean - added this script - * *.[ch] - added $Id: ChangeLog,v 1.80 2003/05/27 18:03:19 masneyb Exp $ tags + * *.[ch] - added $Id: ChangeLog,v 1.81 2003/06/08 15:04:37 masneyb Exp $ tags * debian/* - updated files from Debian maintainer
--- a/lib/Makefile.am Wed May 28 18:37:28 2003 +0000 +++ b/lib/Makefile.am Sun Jun 08 15:04:40 2003 +0000 @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in noinst_LIBRARIES = libgftp.a -libgftp_a_SOURCES=bookmark.c cache.c config_file.c local.c misc.c protocols.c \ - pty.c rfc959.c rfc2068.c sshv2.c +libgftp_a_SOURCES=bookmark.c cache.c config_file.c https.c local.c misc.c \ + protocols.c pty.c rfc959.c rfc2068.c sshv2.c sslcommon.c INCLUDES=@GLIB_CFLAGS@ @PTHREAD_CFLAGS@ -I../intl -DSHARE_DIR=\"$(datadir)/gftp\" -noinst_HEADERS=gftp.h options.h +noinst_HEADERS=gftp.h httpcommon.h options.h
--- a/lib/bookmark.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/bookmark.c Sun Jun 08 15:04:40 2003 +0000 @@ -59,8 +59,11 @@ request->protonum = GFTP_BOOKMARK_NUM; request->init = bookmark_init; + request->read_function = NULL; + request->write_function = NULL; request->destroy = NULL; request->connect = NULL; + request->post_connect = NULL; request->disconnect = NULL; request->get_file = NULL; request->put_file = NULL;
--- a/lib/cache.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/cache.c Sun Jun 08 15:04:40 2003 +0000 @@ -140,7 +140,7 @@ request->directory == NULL ? "" : request->directory, tempstr, request->server_type); g_free (tempstr); - ret = gftp_write (NULL, temp1str, strlen (temp1str), fd); + ret = gftp_fd_write (NULL, temp1str, strlen (temp1str), fd); g_free (temp1str); if (close (fd) != 0 || ret < 0) @@ -333,7 +333,7 @@ as we read it */ gftp_restore_cache_line (¢ry, buf); - if (gftp_write (NULL, buf, strlen (buf), newfd) < 0) + if (gftp_fd_write (NULL, buf, strlen (buf), newfd) < 0) break; } }
--- a/lib/gftp.h Wed May 28 18:37:28 2003 +0000 +++ b/lib/gftp.h Sun Jun 08 15:04:40 2003 +0000 @@ -67,6 +67,14 @@ #include <strings.h> #endif +#ifdef USE_SSL +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/rand.h> +#include <openssl/ssl.h> +#include <openssl/x509v3.h> +#endif + #ifdef ENABLE_NLS #include <libintl.h> #include <locale.h> @@ -334,8 +342,17 @@ void *user_data; void (*init) ( gftp_request * request ); + ssize_t (*read_function) ( gftp_request * request, + void *ptr, + size_t size, + int fd ); + ssize_t (*write_function) ( gftp_request * request, + const char *ptr, + size_t size, + int fd ); void (*destroy) ( gftp_request * request ); int (*connect) ( gftp_request * request ); + int (*post_connect) ( gftp_request * request ); void (*disconnect) ( gftp_request * request ); off_t (*get_file) ( gftp_request * request, const char *filename, @@ -394,6 +411,9 @@ gftp_config_vars * local_options_vars; int num_local_options_vars; GHashTable * local_options_hash; +#ifdef USE_SSL + SSL * ssl; +#endif }; @@ -634,12 +654,15 @@ char *file_prefixstr, char *file_suffixstr ); +char * base64_encode ( char *str ); + /* protocols.c */ #define GFTP_FTP_NUM 0 #define GFTP_HTTP_NUM 1 -#define GFTP_LOCAL_NUM 2 -#define GFTP_SSHV2_NUM 3 -#define GFTP_BOOKMARK_NUM 4 +#define GFTP_HTTPS_NUM 2 +#define GFTP_LOCAL_NUM 3 +#define GFTP_SSHV2_NUM 4 +#define GFTP_BOOKMARK_NUM 5 #define GFTP_IS_CONNECTED(request) ((request) != NULL && \ ((request)->sockfd > 0 || \ @@ -659,6 +682,10 @@ void rfc2068_register_module ( void ); +void https_init ( gftp_request * request ); + +void https_register_module ( void ); + void local_init ( gftp_request * request ); void local_register_module ( void ); @@ -807,18 +834,19 @@ void print_file_list ( GList * list ); + ssize_t gftp_get_line ( gftp_request * request, gftp_getline_buffer ** rbuf, char * str, size_t len, int fd ); -ssize_t gftp_read ( gftp_request * request, +ssize_t gftp_fd_read ( gftp_request * request, void *ptr, size_t size, int fd ); -ssize_t gftp_write ( gftp_request * request, +ssize_t gftp_fd_write ( gftp_request * request, const char *ptr, size_t size, int fd ); @@ -828,7 +856,7 @@ const char *fmt, ... ); -int gftp_set_sockblocking ( gftp_request * request, +int gftp_fd_set_sockblocking ( gftp_request * request, int fd, int non_blocking ); @@ -848,5 +876,24 @@ int tty_raw ( int fd ); +#ifdef USE_SSL +/* sslcommon.c */ +int gftp_ssl_startup ( gftp_request * request ); + +int gftp_ssl_session_setup ( gftp_request * request ); + +void gftp_ssl_free ( gftp_request * request ); + +ssize_t gftp_ssl_read ( gftp_request * request, + void *ptr, + size_t size, + int fd ); + +ssize_t gftp_ssl_write ( gftp_request * request, + const char *ptr, + size_t size, + int fd ); +#endif /* USE_SSL */ + #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/httpcommon.h Sun Jun 08 15:04:40 2003 +0000 @@ -0,0 +1,40 @@ +/*****************************************************************************/ +/* httpcommon.h - common data structures for RFC2068 and HTTPS */ +/* Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org> */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/*****************************************************************************/ + +/* $Id$ */ + +typedef struct rfc2068_params_tag +{ + gftp_getline_buffer * rbuf; + unsigned long read_bytes, + content_length, + chunk_size; + unsigned int chunked_transfer : 1; + ssize_t (*real_read_function) ( gftp_request * request, + void *ptr, + size_t size, + int fd ); + +} rfc2068_params; + +int rfc2068_get_next_file ( gftp_request * request, + gftp_file * fle, + int fd ); + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/https.c Sun Jun 08 15:04:40 2003 +0000 @@ -0,0 +1,76 @@ +/*****************************************************************************/ +/* https.c - General purpose routines for the HTTPS protocol */ +/* Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org> */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */ +/*****************************************************************************/ + +#include "gftp.h" +#include "httpcommon.h" + +static const char cvsid[] = "$Id$"; + +static int +https_get_next_file (gftp_request * request, gftp_file * fle, int fd) +{ + rfc2068_params * params; + int ret, resetptr; + + params = request->protocol_data; + if (request->cached) + { + params->real_read_function = gftp_fd_read; + request->write_function = gftp_fd_write; + resetptr = 1; + } + else + resetptr = 0; + + ret = rfc2068_get_next_file (request, fle, fd); + + if (resetptr) + { + params->real_read_function = gftp_ssl_read; + request->write_function = gftp_ssl_write; + } + + return (ret); +} + + +void +https_register_module (void) +{ + gftp_ssl_startup (NULL); /* FIXME - take out of here */ +} + + +void +https_init (gftp_request * request) +{ + rfc2068_params * params; + + g_return_if_fail (request != NULL); + + gftp_protocols[GFTP_HTTP_NUM].init (request); + params = request->protocol_data; + request->init = https_init; + request->post_connect = gftp_ssl_session_setup; + params->real_read_function = gftp_ssl_read; + request->write_function = gftp_ssl_write; + request->get_next_file = https_get_next_file; + request->url_prefix = g_strdup ("https"); +} +
--- a/lib/local.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/local.c Sun Jun 08 15:04:40 2003 +0000 @@ -647,7 +647,10 @@ request->protonum = GFTP_LOCAL_NUM; request->init = local_init; request->destroy = local_destroy; + request->read_function = gftp_fd_read; + request->write_function = gftp_fd_write; request->connect = local_connect; + request->post_connect = NULL; request->disconnect = local_disconnect; request->get_file = local_get_file; request->put_file = local_put_file;
--- a/lib/misc.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/misc.c Sun Jun 08 15:04:40 2003 +0000 @@ -529,10 +529,8 @@ gftp_transfer * tdata; tdata = g_malloc0 (sizeof (*tdata)); -/* FIXME - tdata->statmutex = G_STATIC_MUTEX_INIT; - tdata->structmutex = G_STATIC_MUTEX_INIT; -*/ + g_static_mutex_init (&tdata->statmutex); + g_static_mutex_init (&tdata->structmutex); return (tdata); } @@ -989,3 +987,51 @@ return (sent); } + +char * +base64_encode (char *str) +{ + +/* The standard to Base64 encoding can be found in RFC2045 */ + + char *newstr, *newpos, *fillpos, *pos; + unsigned char table[64], encode[3]; + int i, num; + + for (i = 0; i < 26; i++) + { + table[i] = 'A' + i; + table[i + 26] = 'a' + i; + } + + for (i = 0; i < 10; i++) + table[i + 52] = '0' + i; + + table[62] = '+'; + table[63] = '-'; + + num = strlen (str) / 3; + if (strlen (str) % 3 > 0) + num++; + newstr = g_malloc (num * 4 + 1); + newstr[num * 4] = '\0'; + newpos = newstr; + + pos = str; + while (*pos != '\0') + { + memset (encode, 0, sizeof (encode)); + for (i = 0; i < 3 && *pos != '\0'; i++) + encode[i] = *pos++; + + fillpos = newpos; + *newpos++ = table[encode[0] >> 2]; + *newpos++ = table[(encode[0] & 3) << 4 | encode[1] >> 4]; + *newpos++ = table[(encode[1] & 0xF) << 2 | encode[2] >> 6]; + *newpos++ = table[encode[2] & 0x3F]; + while (i < 3) + fillpos[++i] = '='; + } + return (newstr); +} +
--- a/lib/options.h Wed May 28 18:37:28 2003 +0000 +++ b/lib/options.h Sun Jun 08 15:04:40 2003 +0000 @@ -179,6 +179,7 @@ { {N_("FTP"), rfc959_init, rfc959_register_module, "ftp", 1}, {N_("HTTP"), rfc2068_init, rfc2068_register_module, "http", 1}, + {N_("HTTPS"), https_init, https_register_module, "https", 1}, {N_("Local"), local_init, local_register_module, "file", 1}, {N_("SSH2"), sshv2_init, sshv2_register_module, "ssh2", 1}, {N_("Bookmark"), bookmark_init, bookmark_register_module, "bookmark", 0},
--- a/lib/protocols.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/protocols.c Sun Jun 08 15:04:40 2003 +0000 @@ -128,6 +128,14 @@ #endif request->hostp = NULL; +#ifdef USE_SSL + if (request->ssl != NULL) + { + SSL_free (request->ssl); + request->ssl = NULL; + } +#endif + request->cached = 0; if (request->disconnect == NULL) return; @@ -227,7 +235,7 @@ if (request->get_next_file_chunk != NULL) return (request->get_next_file_chunk (request, buf, size)); - return (gftp_read (request, buf, size, request->datafd)); + return (request->read_function (request, buf, size, request->datafd)); } @@ -243,7 +251,7 @@ if (size == 0) return (0); - return (gftp_write (request, buf, size, request->datafd)); + return (request->write_function (request, buf, size, request->datafd)); } @@ -364,7 +372,7 @@ if (ret >= 0 && !request->cached && request->cachefd > 0 && request->last_dir_entry != NULL) { - if (gftp_write (request, request->last_dir_entry, + if (gftp_fd_write (request, request->last_dir_entry, request->last_dir_entry_len, request->cachefd) < 0) { request->logging_function (gftp_logging_error, request->user_data, @@ -458,9 +466,9 @@ int gftp_parse_url (gftp_request * request, const char *url) { - char *pos, *endpos, *endhostpos, *str, tempchar, *default_protocol; + char *pos, *endpos, *endhostpos, tempchar, *default_protocol, *stpos; gftp_logging_func logging_function; - const char *stpos; + const char *cpos; int len, i; g_return_val_if_fail (request != NULL, GFTP_EFATAL); @@ -470,7 +478,10 @@ gftp_request_destroy (request, 0); request->logging_function = logging_function; - for (stpos = url; *stpos == ' '; stpos++); + for (cpos = url; *cpos == ' '; cpos++); + stpos = g_strdup (cpos); + for (pos = stpos + strlen (stpos) - 1; *pos == ' '; pos--) + *pos = '\0'; i = GFTP_FTP_NUM; @@ -484,9 +495,13 @@ break; } + *pos = ':'; + if (gftp_protocols[i].url_prefix == NULL) - return (GFTP_EFATAL); - *pos = ':'; + { + g_free (stpos); + return (GFTP_EFATAL); + } } else { @@ -509,48 +524,47 @@ gftp_protocols[i].init (request); if (request->parse_url != NULL) - return (request->parse_url (request, url)); + { + g_free (stpos); + return (request->parse_url (request, url)); + } + + pos = stpos; + len = strlen (request->url_prefix); + if (strncmp (pos, request->url_prefix, len) == 0 && + strncmp (pos + len, "://", 3) == 0) + pos += len + 3; if (i == GFTP_LOCAL_NUM) { - request->directory = g_strdup (stpos + 7); + request->directory = g_strdup (pos); + g_free (stpos); return (0); } - for (; *stpos == ' '; stpos++); - str = g_strdup (stpos); - for (pos = str + strlen (str) - 1; *pos == ' '; pos--) - *pos = '\0'; - - pos = str; - len = strlen (request->url_prefix); - if (strncmp (pos, request->url_prefix, len) == 0 - && strncmp (pos + len, "://", 3) == 0) - pos += len + 3; - if ((endhostpos = strchr (pos, '@')) != NULL) { /* A user/password was entered */ if ((endpos = strchr (pos, ':')) == NULL || endhostpos < endpos) - { - /* No password was entered */ - gftp_set_password (request, ""); - endpos = endhostpos; - } + { + /* No password was entered */ + gftp_set_password (request, ""); + endpos = endhostpos; + } *endpos = '\0'; gftp_set_username (request, pos); pos = endpos + 1; if ((endpos = strchr (pos, '@')) != NULL) - { - if (strchr (endpos + 1, '@') != NULL) - endpos = strchr (endpos + 1, '@'); - *endpos = '\0'; - gftp_set_password (request, pos); + { + if (strchr (endpos + 1, '@') != NULL) + endpos = strchr (endpos + 1, '@'); + *endpos = '\0'; + gftp_set_password (request, pos); - pos = endpos + 1; - } + pos = endpos + 1; + } } /* Now get the hostname and an optional port and optional directory */ @@ -572,7 +586,7 @@ } if ((endpos = strchr (pos, '/')) != NULL) gftp_set_directory (request, endpos); - g_free (str); + g_free (stpos); return (0); } @@ -635,11 +649,11 @@ if (request->sockfd <= 0 && !request->always_connected) { if (directory != request->directory) - { - if (request->directory) - g_free (request->directory); - request->directory = g_strdup (directory); - } + { + if (request->directory) + g_free (request->directory); + request->directory = g_strdup (directory); + } return (0); } else if (request->chdir == NULL) @@ -692,7 +706,7 @@ int gftp_rename_file (gftp_request * request, const char *oldname, - const char *newname) + const char *newname) { g_return_val_if_fail (request != NULL, GFTP_EFATAL); @@ -822,23 +836,23 @@ hostname = templist->data; if (hostname->domain && strlen (request->hostname) > strlen (hostname->domain)) - { - pos = request->hostname + strlen (request->hostname) - - strlen (hostname->domain); - if (strcmp (hostname->domain, pos) == 0) - return (0); - } + { + pos = request->hostname + strlen (request->hostname) - + strlen (hostname->domain); + if (strcmp (hostname->domain, pos) == 0) + return (0); + } if (hostname->ipv4_network_address != 0) - { - memcpy (addy, addr, sizeof (addy)); - netaddr = - (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) | - ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & + { + memcpy (addy, addr, sizeof (addy)); + netaddr = + (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) | + ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) & hostname->ipv4_netmask; - if (netaddr == hostname->ipv4_network_address) - return (0); - } + if (netaddr == hostname->ipv4_network_address) + return (0); + } templist = templist->next; } @@ -894,6 +908,7 @@ struct tm curtime, *loctime; time_t t, ret; char *tmppos; + int i; memset (&curtime, 0, sizeof (curtime)); curtime.tm_isdst = -1; @@ -937,7 +952,8 @@ /* We cannot parse this date format. So, just skip this date field and continue to the next token. This is mainly for the HTTP support */ - for (*endpos = str; **endpos != ' ' && **endpos != '\t' && **endpos != '\0'; *endpos++); + for (i=0, *endpos = str; (*endpos)[i] != ' ' && (*endpos)[i] != '\t' && (*endpos)[i] != '\0'; i++); + endpos += i; } else *endpos = tmppos; @@ -1033,17 +1049,17 @@ { startpos++; switch (*startpos) - { - case '/': - *fle->attribs = 'd'; - break; - case 's': - fle->size = strtol (startpos + 1, NULL, 10); - break; - case 'm': - fle->datetime = strtol (startpos + 1, NULL, 10); - break; - } + { + case '/': + *fle->attribs = 'd'; + break; + case 's': + fle->size = strtol (startpos + 1, NULL, 10); + break; + case 'm': + fle->datetime = strtol (startpos + 1, NULL, 10); + break; + } startpos = strchr (startpos, ','); } if ((startpos = strchr (str, 9)) == NULL) @@ -1101,20 +1117,20 @@ /* Copy the user that owns this file */ if ((startpos = copy_token (&fle->user, startpos)) == NULL) - return (GFTP_EFATAL); + return (GFTP_EFATAL); /* Copy the group that owns this file */ if ((startpos = copy_token (&fle->group, startpos)) == NULL) - return (GFTP_EFATAL); + return (GFTP_EFATAL); } else { fle->group = g_strdup (_("unknown")); if (cols == 8) - { - if ((startpos = copy_token (&fle->user, startpos)) == NULL) - return (GFTP_EFATAL); - } + { + if ((startpos = copy_token (&fle->user, startpos)) == NULL) + return (GFTP_EFATAL); + } else fle->user = g_strdup (_("unknown")); startpos = goto_next_token (startpos); @@ -1141,18 +1157,18 @@ startpos = endpos + 1; while (*startpos == ' ') - startpos++; + startpos++; /* Get the minor number */ if ((endpos = strchr (startpos, ' ')) == NULL) - return (GFTP_EFATAL); + return (GFTP_EFATAL); fle->size |= strtol (startpos, NULL, 10) & 0xFF; } else { /* This is a regular file */ if ((endpos = strchr (startpos, ' ')) == NULL) - return (GFTP_EFATAL); + return (GFTP_EFATAL); fle->size = strtol (startpos, NULL, 10); } @@ -1599,15 +1615,15 @@ snprintf (serv, sizeof (serv), "%d", port); request->logging_function (gftp_logging_misc, request->user_data, - _("Looking up %s\n"), connect_host); + _("Looking up %s\n"), connect_host); if ((errnum = getaddrinfo (connect_host, serv, &hints, &request->hostp)) != 0) - { - request->logging_function (gftp_logging_error, request->user_data, - _("Cannot look up hostname %s: %s\n"), - connect_host, gai_strerror (errnum)); - return (GFTP_ERETRYABLE); - } + { + request->logging_function (gftp_logging_error, request->user_data, + _("Cannot look up hostname %s: %s\n"), + connect_host, gai_strerror (errnum)); + return (GFTP_ERETRYABLE); + } } disphost = connect_host; @@ -1621,23 +1637,23 @@ if ((sock = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) { - request->logging_function (gftp_logging_error, request->user_data, + request->logging_function (gftp_logging_error, request->user_data, _("Failed to create a socket: %s\n"), g_strerror (errno)); continue; } request->logging_function (gftp_logging_misc, request->user_data, - _("Trying %s:%d\n"), disphost, port); + _("Trying %s:%d\n"), disphost, port); if (connect (sock, res->ai_addr, res->ai_addrlen) == -1) - { - request->logging_function (gftp_logging_error, request->user_data, - _("Cannot connect to %s: %s\n"), - disphost, g_strerror (errno)); + { + request->logging_function (gftp_logging_error, request->user_data, + _("Cannot connect to %s: %s\n"), + disphost, g_strerror (errno)); close (sock); continue; - } + } break; } @@ -1708,7 +1724,7 @@ if (request->hostp == NULL) { request->logging_function (gftp_logging_misc, request->user_data, - _("Looking up %s\n"), connect_host); + _("Looking up %s\n"), connect_host); if (!(request->hostp = r_gethostbyname (connect_host, &request->host, NULL))) { @@ -1749,15 +1765,20 @@ #endif /* HAVE_GETADDRINFO */ request->logging_function (gftp_logging_misc, request->user_data, - _("Connected to %s:%d\n"), connect_host, port); + _("Connected to %s:%d\n"), connect_host, port); - if (gftp_set_sockblocking (request, sock, 1) < 0) + if (gftp_fd_set_sockblocking (request, sock, 1) < 0) { close (sock); return (GFTP_ERETRYABLE); } - return (sock); + request->sockfd = sock; + + if (request->post_connect != NULL) + return (request->post_connect (request)); + + return (0); } @@ -1823,27 +1844,35 @@ gftp_get_line (gftp_request * request, gftp_getline_buffer ** rbuf, char * str, size_t len, int fd) { - ssize_t ret, retval, rlen, copysize; + ssize_t ret, retval, rlen; char *pos, *nextpos; + ssize_t (*read_function) (gftp_request * request, void *ptr, size_t size, + int fd); + + if (request == NULL || request->read_function == NULL) + read_function = gftp_fd_read; + else + read_function = request->read_function; if (*rbuf == NULL) { *rbuf = g_malloc0 (sizeof (**rbuf)); (*rbuf)->max_bufsize = len; (*rbuf)->buffer = g_malloc ((*rbuf)->max_bufsize + 1); - if ((ret = gftp_read (request, (*rbuf)->buffer, (*rbuf)->max_bufsize, - fd)) <= 0) + + if ((ret = read_function (request, (*rbuf)->buffer, + (*rbuf)->max_bufsize, fd)) <= 0) { gftp_free_getline_buffer (rbuf); return (ret); } + (*rbuf)->buffer[ret] = '\0'; (*rbuf)->cur_bufsize = ret; (*rbuf)->curpos = (*rbuf)->buffer; } retval = GFTP_ERETRYABLE; - do { if ((*rbuf)->cur_bufsize > 0 && @@ -1852,6 +1881,11 @@ (*rbuf)->max_bufsize == (*rbuf)->cur_bufsize))) { if (pos != NULL) + retval = pos - (*rbuf)->curpos + 1; + else + retval = (*rbuf)->cur_bufsize; + + if (pos != NULL) { nextpos = pos + 1; if (pos > (*rbuf)->curpos && *(pos - 1) == '\r') @@ -1862,16 +1896,12 @@ nextpos = NULL; strncpy (str, (*rbuf)->curpos, len); - retval = pos - (*rbuf)->curpos > len ? len : pos - (*rbuf)->curpos; + (*rbuf)->cur_bufsize -= retval; - if (pos != NULL) - { - if (nextpos - (*rbuf)->buffer >= (*rbuf)->cur_bufsize) - (*rbuf)->cur_bufsize = 0; - else - (*rbuf)->curpos = nextpos; - } - + if (nextpos != NULL) + (*rbuf)->curpos = nextpos; + else + (*rbuf)->cur_bufsize = 0; break; } else @@ -1880,24 +1910,29 @@ { rlen = (*rbuf)->max_bufsize; pos = (*rbuf)->buffer; - copysize = 0; } else { - copysize = (*rbuf)->cur_bufsize - ((*rbuf)->curpos - (*rbuf)->buffer); - memmove ((*rbuf)->buffer, (*rbuf)->curpos, copysize); - pos = (*rbuf)->buffer + copysize; - rlen = (*rbuf)->max_bufsize - copysize; + memmove ((*rbuf)->buffer, (*rbuf)->curpos, (*rbuf)->cur_bufsize); + pos = (*rbuf)->buffer + (*rbuf)->cur_bufsize; + rlen = (*rbuf)->max_bufsize - (*rbuf)->cur_bufsize; } + (*rbuf)->curpos = (*rbuf)->buffer; - if ((ret = gftp_read (request, pos, rlen, fd)) <= 0) + if ((ret = read_function (request, pos, rlen, fd)) < 0) { gftp_free_getline_buffer (rbuf); return (ret); } - (*rbuf)->buffer[ret + copysize] = '\0'; - (*rbuf)->cur_bufsize = ret + copysize; + else if (ret == 0 && (*rbuf)->cur_bufsize == 0) + { + gftp_free_getline_buffer (rbuf); + return (ret); + } + + (*rbuf)->buffer[ret + (*rbuf)->cur_bufsize] = '\0'; + (*rbuf)->cur_bufsize += ret; } } while (retval == GFTP_ERETRYABLE); @@ -1907,7 +1942,7 @@ ssize_t -gftp_read (gftp_request * request, void *ptr, size_t size, int fd) +gftp_fd_read (gftp_request * request, void *ptr, size_t size, int fd) { long network_timeout; struct timeval tv; @@ -1977,7 +2012,7 @@ ssize_t -gftp_write (gftp_request * request, const char *ptr, size_t size, int fd) +gftp_fd_write (gftp_request * request, const char *ptr, size_t size, int fd) { long network_timeout; struct timeval tv; @@ -2061,14 +2096,14 @@ tempstr = g_strdup_vprintf (fmt, argp); va_end (argp); - ret = gftp_write (request, tempstr, strlen (tempstr), fd); + ret = request->write_function (request, tempstr, strlen (tempstr), fd); g_free (tempstr); return (ret); } int -gftp_set_sockblocking (gftp_request * request, int fd, int non_blocking) +gftp_fd_set_sockblocking (gftp_request * request, int fd, int non_blocking) { int flags;
--- a/lib/rfc2068.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/rfc2068.c Sun Jun 08 15:04:40 2003 +0000 @@ -18,6 +18,8 @@ /*****************************************************************************/ #include "gftp.h" +#include "httpcommon.h" + static const char cvsid[] = "$Id$"; static gftp_config_vars config_vars[] = @@ -44,75 +46,20 @@ {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL} }; -typedef struct rfc2068_params_tag -{ - gftp_getline_buffer * rbuf; - unsigned long read_bytes, - max_bytes; - int chunked_transfer : 1; -} rfc2068_params; - - -static char * -base64_encode (char *str) -{ - -/* The standard to Base64 encoding can be found in RFC2045 */ - - char *newstr, *newpos, *fillpos, *pos; - unsigned char table[64], encode[3]; - int i, num; - - for (i = 0; i < 26; i++) - { - table[i] = 'A' + i; - table[i + 26] = 'a' + i; - } - - for (i = 0; i < 10; i++) - table[i + 52] = '0' + i; - - table[62] = '+'; - table[63] = '-'; - - num = strlen (str) / 3; - if (strlen (str) % 3 > 0) - num++; - newstr = g_malloc (num * 4 + 1); - newstr[num * 4] = '\0'; - newpos = newstr; - - pos = str; - while (*pos != '\0') - { - memset (encode, 0, sizeof (encode)); - for (i = 0; i < 3 && *pos != '\0'; i++) - encode[i] = *pos++; - - fillpos = newpos; - *newpos++ = table[encode[0] >> 2]; - *newpos++ = table[(encode[0] & 3) << 4 | encode[1] >> 4]; - *newpos++ = table[(encode[1] & 0xF) << 2 | encode[2] >> 6]; - *newpos++ = table[encode[2] & 0x3F]; - while (i < 3) - fillpos[++i] = '='; - } - return (newstr); -} - static off_t rfc2068_read_response (gftp_request * request) { rfc2068_params * params; - char tempstr[255]; - int ret; + char tempstr[512]; + int ret, chunked; params = request->protocol_data; - params->chunked_transfer = 0; + chunked = 0; + params->chunk_size = 0; params->rbuf = NULL; *tempstr = '\0'; - params->max_bytes = 0; + params->content_length = 0; if (request->last_ftp_response) { g_free (request->last_ftp_response); @@ -121,8 +68,8 @@ do { - if ((ret = gftp_get_line (request, ¶ms->rbuf, tempstr, sizeof (tempstr), - request->sockfd)) < 0) + if ((ret = gftp_get_line (request, ¶ms->rbuf, tempstr, + sizeof (tempstr), request->sockfd)) < 0) return (ret); if (request->last_ftp_response == NULL) @@ -134,20 +81,48 @@ tempstr); if (strncmp (tempstr, "Content-Length:", 15) == 0) - params->max_bytes = strtol (tempstr + 16, NULL, 10); - if (strcmp (tempstr, "Transfer-Encoding: chunked") == 0) - params->chunked_transfer = 1; + params->content_length = strtol (tempstr + 16, NULL, 10); + else if (strcmp (tempstr, "Transfer-Encoding: chunked") == 0) + chunked = 1; } } while (*tempstr != '\0'); - return (params->max_bytes); + if (chunked) + { + if ((ret = gftp_get_line (request, ¶ms->rbuf, tempstr, + sizeof (tempstr), request->sockfd)) < 0) + return (ret); + + if (sscanf ((char *) tempstr, "%lx", ¶ms->chunk_size) != 1) + { + request->logging_function (gftp_logging_recv, request->user_data, + _("Received wrong response from server, disconnecting\n")); + gftp_disconnect (request); + return (GFTP_EFATAL); + } + + if (params->chunk_size == 0) + return (0); + + params->chunk_size -= params->rbuf->cur_bufsize; + + if (params->chunk_size < 0) + { + request->logging_function (gftp_logging_recv, request->user_data, "FIXME - the chunk size is negative. aborting directory listing\n"); + return (GFTP_EFATAL); + } + + + } + + params->chunked_transfer = chunked; + return (params->content_length > 0 ? params->content_length : params->chunk_size); } static off_t -rfc2068_send_command (gftp_request * request, const char *command, - const char *extrahdr) +rfc2068_send_command (gftp_request * request, const void *command, size_t len) { char *tempstr, *str, *proxy_hostname, *proxy_username, *proxy_password; int proxy_port; @@ -157,13 +132,14 @@ g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL); g_return_val_if_fail (command != NULL, GFTP_EFATAL); - tempstr = g_strdup_printf ("%sUser-Agent: %s\nHost: %s\n", command, + tempstr = g_strdup_printf ("%sUser-Agent: %s\nHost: %s\n", (char *) command, gftp_version, request->hostname); request->logging_function (gftp_logging_send, request->user_data, "%s", tempstr); - ret = gftp_write (request, tempstr, strlen (tempstr), request->sockfd); + ret = request->write_function (request, tempstr, strlen (tempstr), + request->sockfd); g_free (tempstr); if (ret < 0) @@ -186,7 +162,7 @@ "Proxy-authorization: Basic %s\n", str); g_free (str); if (ret < 0) - return (ret); + return (ret); } if (request->username != NULL && *request->username != '\0') @@ -201,19 +177,10 @@ "Authorization: Basic %s\n", str); g_free (str); if (ret < 0) - return (ret); - } - - if (extrahdr) - { - request->logging_function (gftp_logging_send, request->user_data, "%s", - extrahdr); - if ((ret = gftp_write (request, extrahdr, strlen (extrahdr), - request->sockfd)) < 0) return (ret); } - if ((ret = gftp_write (request, "\n", 1, request->sockfd)) < 0) + if ((ret = request->write_function (request, "\n", 1, request->sockfd)) < 0) return (ret); return (rfc2068_read_response (request)); @@ -240,16 +207,14 @@ gftp_lookup_request_option (request, "http_proxy_host", &proxy_hostname); gftp_lookup_request_option (request, "http_proxy_port", &proxy_port); - if (request->url_prefix != NULL) - g_free (request->url_prefix); + if (proxy_config != NULL && strcmp (proxy_config, "ftp") == 0) + { + g_free (request->url_prefix); + request->url_prefix = g_strdup ("ftp"); + } - if (proxy_config != NULL && strcmp (proxy_config, "ftp") == 0) - request->url_prefix = g_strdup ("ftp"); - else - request->url_prefix = g_strdup ("http"); - - if ((request->sockfd = gftp_connect_server (request, request->url_prefix, - proxy_hostname, proxy_port)) < 0) + if (gftp_connect_server (request, request->url_prefix, proxy_hostname, + proxy_port) < 0) return (GFTP_ERETRYABLE); if (request->directory && *request->directory == '\0') @@ -291,8 +256,8 @@ rfc2068_get_file (gftp_request * request, const char *filename, int fd, off_t startsize) { - char *tempstr, *extrahdr, *pos; int restarted, ret, use_http11; + char *tempstr, *oldstr, *pos; rfc2068_params * params; off_t size; @@ -324,27 +289,29 @@ else remove_double_slashes (tempstr); - if (!use_http11 || startsize == 0) - extrahdr = NULL; - else + if (use_http11 && startsize > 0) { #if defined (_LARGEFILE_SOURCE) - extrahdr = g_strdup_printf ("Range: bytes=%lld-\n", startsize); request->logging_function (gftp_logging_misc, request->user_data, _("Starting the file transfer at offset %lld\n"), startsize); + + oldstr = tempstr; + tempstr = g_strdup_printf ("%sRange: bytes=%lld-\n", tempstr, startsize); + g_free (oldstr); #else - extrahdr = g_strdup_printf ("Range: bytes=%ld-\n", startsize); request->logging_function (gftp_logging_misc, request->user_data, _("Starting the file transfer at offset %ld\n"), startsize); + + oldstr = tempstr; + tempstr = g_strdup_printf ("%sRange: bytes=%ld-\n", tempstr, startsize); + g_free (oldstr); #endif } - size = rfc2068_send_command (request, tempstr, extrahdr); + size = rfc2068_send_command (request, tempstr, strlen (tempstr)); g_free (tempstr); - if (extrahdr) - g_free (extrahdr); if (size < 0) return (size); @@ -360,6 +327,8 @@ return (GFTP_ERETRYABLE); } + params->read_bytes = 0; + return (restarted ? size + startsize : size); } @@ -374,14 +343,8 @@ g_return_val_if_fail (request->protonum == GFTP_HTTP_NUM, GFTP_EFATAL); params = request->protocol_data; - if (params->max_bytes == params->read_bytes) - return (0); - if (params->max_bytes > 0 && - size + params->read_bytes > params->max_bytes) - size = params->max_bytes - params->read_bytes; - - if ((len = gftp_read (request, buf, size, request->sockfd)) < 0) + if ((len = request->read_function (request, buf, size, request->sockfd)) < 0) return ((ssize_t) len); return (len); @@ -406,7 +369,9 @@ request->sockfd = -1; params = request->protocol_data; - params->max_bytes = 0; + params->content_length = 0; + params->chunked_transfer = 0; + params->chunk_size = 0; request->logging_function (gftp_logging_misc, request->user_data, _("Finished retrieving data\n")); @@ -446,7 +411,7 @@ else remove_double_slashes (tempstr); - ret = rfc2068_send_command (request, tempstr, NULL); + ret = rfc2068_send_command (request, tempstr, strlen (tempstr)); g_free (tempstr); if (ret < 0) return ((int) ret); @@ -459,7 +424,7 @@ _("Retrieving directory listing...\n")); return (0); } - + return (GFTP_ERETRYABLE); } @@ -496,7 +461,7 @@ else remove_double_slashes (tempstr); - size = rfc2068_send_command (request, tempstr, NULL); + size = rfc2068_send_command (request, tempstr, strlen (tempstr)); g_free (tempstr); return (size); } @@ -584,6 +549,9 @@ fle->datetime = parse_time (pos, &pos); + fle->user = g_strdup (_("<unknown>")); + fle->group = g_strdup (_("<unknown>")); + if (pos == NULL) return (1); @@ -613,21 +581,22 @@ if ((*stpos == '.') && isdigit (*(stpos + 1)) ) { /* found decimal point */ fle->size = units * strtol (stpos + 1, NULL, 10); - fle->size /= 10; + fle->size /= 10; /* FIXME */ } } fle->size += units * strtol (stpos, NULL, 10); + return (1); } -static int +int rfc2068_get_next_file (gftp_request * request, gftp_file * fle, int fd) { rfc2068_params * params; char tempstr[255]; - size_t len; + ssize_t len; int ret; g_return_val_if_fail (request != NULL, GFTP_EFATAL); @@ -646,35 +615,13 @@ while (1) { - if ((ret = gftp_get_line (request, ¶ms->rbuf, tempstr, sizeof (tempstr), - fd)) < 0) + if ((ret = gftp_get_line (request, ¶ms->rbuf, tempstr, sizeof (tempstr), fd)) <= 0) return (ret); - params->read_bytes += strlen (tempstr); - - if (params->chunked_transfer && strcmp (tempstr, "0") == 0) - { - while ((len = gftp_get_line (request, ¶ms->rbuf, tempstr, - sizeof (tempstr), fd)) > 0) - { - if (*tempstr == '\0') - break; - } - gftp_file_destroy (fle); - - if (len < 0) - return (len); - - return (0); - } - if (parse_html_line (tempstr, fle) == 0 || fle->file == NULL) gftp_file_destroy (fle); else break; - - if (params->max_bytes != 0 && params->read_bytes == params->max_bytes) - break; } if (fle->file == NULL) @@ -727,6 +674,91 @@ } +static ssize_t +rfc2068_chunked_read (gftp_request * request, void *ptr, size_t size, int fd) +{ + rfc2068_params * params; + char *stpos, *endpos; + size_t read_size; + ssize_t retval; + + params = request->protocol_data; + + read_size = size; + if (params->content_length > 0) + { + if (params->content_length == params->read_bytes) + return (0); + + if (read_size + params->read_bytes > params->content_length) + read_size = params->content_length - params->read_bytes; + } + else if (params->chunked_transfer && params->chunk_size > 0 && + params->chunk_size < read_size) + read_size = params->chunk_size; + + retval = params->real_read_function (request, ptr, read_size, fd); + + if (retval > 0) + params->read_bytes += retval; + + if (!params->chunked_transfer || retval <= 0) + return (retval); + + if (params->chunk_size == 0) + { + stpos = (char *) ptr; + + while (params->chunk_size == 0) + { + if (*stpos != '\r' || *(stpos + 1) != '\n') + { + request->logging_function (gftp_logging_recv, request->user_data, + _("Received wrong response from server, disconnecting\n")); + gftp_disconnect (request); + return (GFTP_EFATAL); + } + + for (endpos = stpos + 2; + *endpos != '\n'; + endpos++); + + /* FIXME extra checks */ + + *endpos = '\0'; + if (*(endpos - 1) == '\r') + *(endpos - 1) = '\0'; + + if (sscanf (stpos + 2, "%lx", ¶ms->chunk_size) != 1) + { + request->logging_function (gftp_logging_recv, request->user_data, + _("Received wrong response from server, disconnecting\n")); + gftp_disconnect (request); + return (GFTP_EFATAL); + } + + if (params->chunk_size == 0) + return (0); + + retval -= endpos - (char *) ptr + 1; + params->chunk_size -= retval; + memmove (stpos, endpos + 1, retval); + ((char *) stpos)[retval] = '\0'; + + if (params->chunk_size == 0) + { + stpos += params->chunk_size; + continue; + } + } + } + else if (retval > 0) + params->chunk_size -= retval; + + return (retval); +} + + void rfc2068_register_module (void) { @@ -737,12 +769,17 @@ void rfc2068_init (gftp_request * request) { + rfc2068_params * params; + g_return_if_fail (request != NULL); request->protonum = GFTP_HTTP_NUM; request->init = rfc2068_init; + request->read_function = rfc2068_chunked_read; + request->write_function = gftp_fd_write; request->destroy = rfc2068_destroy; request->connect = rfc2068_connect; + request->post_connect = NULL; request->disconnect = rfc2068_disconnect; request->get_file = rfc2068_get_file; request->put_file = NULL; @@ -770,7 +807,11 @@ request->use_cache = 1; request->use_threads = 1; request->always_connected = 1; + request->protocol_data = g_malloc0 (sizeof (rfc2068_params)); + params = request->protocol_data; + params->real_read_function = gftp_fd_read; + gftp_set_config_options (request); }
--- a/lib/rfc959.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/rfc959.c Sun Jun 08 15:04:40 2003 +0000 @@ -165,7 +165,7 @@ command); } - if ((ret = gftp_write (request, command, strlen (command), + if ((ret = gftp_fd_write (request, command, strlen (command), request->sockfd)) < 0) return (ret); @@ -435,8 +435,7 @@ else if (strcasecmp (request->username, "anonymous") == 0) gftp_set_password (request, email); - if ((request->sockfd = gftp_connect_server (request, "ftp", proxy_hostname, - proxy_port)) < 0) + if (gftp_connect_server (request, "ftp", proxy_hostname, proxy_port) < 0) return (request->sockfd); /* Get the banner */ @@ -879,7 +878,7 @@ cli_addr_len = sizeof (cli_addr); - if ((ret = gftp_set_sockblocking (request, request->datafd, 0)) < 0) + if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 0)) < 0) return (ret); if ((infd = accept (request->datafd, (struct sockaddr *) &cli_addr, @@ -895,7 +894,7 @@ close (request->datafd); request->datafd = infd; - if ((ret = gftp_set_sockblocking (request, request->datafd, 1)) < 0) + if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 1)) < 0) return (ret); return (0); @@ -985,7 +984,7 @@ (ret = rfc959_data_connection_new (request)) < 0) return (ret); - if ((ret = gftp_set_sockblocking (request, request->datafd, 1)) < 0) + if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 1)) < 0) return (ret); if (startsize > 0) @@ -1056,7 +1055,7 @@ (ret = rfc959_data_connection_new (request)) < 0) return (ret); - if ((ret = gftp_set_sockblocking (request, request->datafd, 1)) < 0) + if ((ret = gftp_fd_set_sockblocking (request, request->datafd, 1)) < 0) return (ret); if (startsize > 0) @@ -1137,7 +1136,7 @@ g_free (tempstr); tempstr = g_strconcat ("RETR ", fromfile, "\r\n", NULL); - if ((ret = gftp_write (fromreq, tempstr, strlen (tempstr), + if ((ret = gftp_fd_write (fromreq, tempstr, strlen (tempstr), fromreq->sockfd)) < 0) { g_free (tempstr); @@ -1146,7 +1145,8 @@ g_free (tempstr); tempstr = g_strconcat ("STOR ", tofile, "\r\n", NULL); - if ((ret = gftp_write (toreq, tempstr, strlen (tempstr), toreq->sockfd)) < 0) + if ((ret = gftp_fd_write (toreq, tempstr, strlen (tempstr), + toreq->sockfd)) < 0) { g_free (tempstr); return (ret); @@ -1262,7 +1262,7 @@ int i, j, ascii_transfers; ssize_t num_read; - num_read = gftp_read (request, buf, size, request->datafd); + num_read = gftp_fd_read (request, buf, size, request->datafd); if (num_read < 0) return (num_read); @@ -1324,7 +1324,7 @@ tempstr = buf; } - num_wrote = gftp_write (request, tempstr, rsize, request->datafd); + num_wrote = gftp_fd_write (request, tempstr, rsize, request->datafd); if (tempstr != buf) g_free (tempstr); @@ -1381,7 +1381,7 @@ if (!request->cached) { request->last_dir_entry = g_strdup_printf ("%s\n", tempstr); - request->last_dir_entry_len = len + 1; + request->last_dir_entry_len = strlen (tempstr) + 1; } return (len); } @@ -1609,7 +1609,10 @@ request->protonum = GFTP_FTP_NUM; request->init = rfc959_init; request->destroy = NULL; + request->read_function = gftp_fd_read; + request->write_function = gftp_fd_write; request->connect = rfc959_connect; + request->post_connect = NULL; request->disconnect = rfc959_disconnect; request->get_file = rfc959_get_file; request->put_file = rfc959_put_file;
--- a/lib/sshv2.c Wed May 28 18:37:28 2003 +0000 +++ b/lib/sshv2.c Sun Jun 08 15:04:40 2003 +0000 @@ -269,7 +269,7 @@ wrotepw = 0; ok = 1; - if (gftp_set_sockblocking (request, fd, 1) == -1) + if (gftp_fd_set_sockblocking (request, fd, 1) == -1) return (NULL); pwstr = g_strconcat (request->password, "\n", NULL); @@ -277,7 +277,7 @@ errno = 0; while (1) { - if ((rd = gftp_read (request, tempstr + diff, rem - 1, fd)) <= 0) + if ((rd = gftp_fd_read (request, tempstr + diff, rem - 1, fd)) <= 0) { ok = 0; break; @@ -302,7 +302,7 @@ } wrotepw = 1; - if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0) + if (gftp_fd_write (request, pwstr, strlen (pwstr), fd) < 0) { ok = 0; break; @@ -327,7 +327,7 @@ } wrotepw = 1; - if (gftp_write (request, pwstr, strlen (pwstr), fd) < 0) + if (gftp_fd_write (request, pwstr, strlen (pwstr), fd) < 0) { ok = 0; break; @@ -585,7 +585,7 @@ sshv2_log_command (request, gftp_logging_send, type, buf + 5, len); - if ((ret = gftp_write (request, buf, len + 5, request->sockfd)) < 0) + if ((ret = gftp_fd_write (request, buf, len + 5, request->sockfd)) < 0) return (ret); return (0); @@ -606,7 +606,7 @@ rem = 5; while (rem > 0) { - if ((numread = gftp_read (request, pos, rem, fd)) < 0) + if ((numread = gftp_fd_read (request, pos, rem, fd)) < 0) return ((int) numread); rem -= numread; pos += numread; @@ -634,7 +634,7 @@ rem = message->length - 1; while (rem > 0) { - if ((numread = gftp_read (request, pos, rem, fd)) < 0) + if ((numread = gftp_fd_read (request, pos, rem, fd)) < 0) return ((int) numread); rem -= numread; pos += numread; @@ -2255,7 +2255,10 @@ request->protonum = GFTP_SSHV2_NUM; request->init = sshv2_init; request->destroy = sshv2_destroy; + request->read_function = gftp_fd_read; + request->write_function = gftp_fd_write; request->connect = sshv2_connect; + request->post_connect = NULL; request->disconnect = sshv2_disconnect; request->get_file = sshv2_get_file; request->put_file = sshv2_put_file;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/sslcommon.c Sun Jun 08 15:04:40 2003 +0000 @@ -0,0 +1,345 @@ +/*****************************************************************************/ +/* sslcommon.c - interface to OpenSSL */ +/* Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org> */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */ +/*****************************************************************************/ + +#include "gftp.h" + +static const char cvsid[] = "$Id$"; + +/* Some of the functions in here was taken either entirely or partially from + * the O'Reilly book Network Security with OpenSSL */ + +static SSL_CTX * ctx = NULL; + +#ifdef USE_SSL + +static volatile int gftp_ssl_initialized = 0; + +static int +gftp_ssl_verify_callback (int ok, X509_STORE_CTX *store) +{ + char data[256]; + + if (!ok) + { + X509 *cert = X509_STORE_CTX_get_current_cert (store); + int depth = X509_STORE_CTX_get_error_depth (store); + int err = X509_STORE_CTX_get_error (store); + + fprintf (stderr, "-Error with certificate at depth: %i\n", depth); + X509_NAME_oneline (X509_get_issuer_name (cert), data, sizeof (data)); + fprintf (stderr, " issuer = %s\n", data); + X509_NAME_oneline (X509_get_subject_name (cert), data, sizeof (data)); + fprintf (stderr, " subject = %s\n", data); + fprintf (stderr, " err %i:%s\n", err, X509_verify_cert_error_string (err)); + } + + return ok; +} + + +static int +gftp_ssl_post_connection_check (gftp_request * request) +{ + char data[256], *extstr; + int extcount, ok, i, j; + X509_EXTENSION *ext; + X509_NAME *subj; + X509 *cert; + + ok = 0; + if (!(cert = SSL_get_peer_certificate (request->ssl))) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Cannot get peer certificate\n")); + return (X509_V_ERR_APPLICATION_VERIFICATION); + } + + if ((extcount = X509_get_ext_count (cert)) > 0) + { + for (i = 0; i < extcount; i++) + { + ext = X509_get_ext (cert, i); + extstr = (char *) OBJ_nid2sn (OBJ_obj2nid (X509_EXTENSION_get_object (ext))); + + if (strcmp (extstr, "subjectAltName") == 0) + { + unsigned char *data; + STACK_OF(CONF_VALUE) *val; + CONF_VALUE *nval; + X509V3_EXT_METHOD *meth; + void *ext_str = NULL; + + if (!(meth = X509V3_EXT_get(ext))) + break; + data = ext->value->data; + +#if (OPENSSL_VERSION_NUMBER > 0x00907000L) + if (meth->it) + ext_str = ASN1_item_d2i(NULL, &data, ext->value->length, + ASN1_ITEM_ptr(meth->it)); + else + ext_str = meth->d2i(NULL, &data, ext->value->length); +#else + ext_str = meth->d2i(NULL, &data, ext->value->length); +#endif + val = meth->i2v(meth, ext_str, NULL); + for (j = 0; j < sk_CONF_VALUE_num(val); j++) + { + nval = sk_CONF_VALUE_value(val, j); + if (strcmp(nval->name, "DNS") == 0 && strcmp(nval->value, request->hostname) == 0) + { + ok = 1; + break; + } + } + } + if (ok) + break; + } + } + +/* FIXME + if (!ok && (subj = X509_get_subject_name (cert)) && + X509_NAME_get_text_by_NID (subj, NID_commonName, data, 256) > 0) + { + data[sizeof (data) - 1] = '\0'; + if (strcasecmp (data, request->hostname) != 0) + { + request->logging_function (gftp_logging_error, request->user_data, + _("The SSL certificate's host %s does not match the host %s that we connected to\n"), + data, request->hostname); + X509_free (cert); + return (X509_V_ERR_APPLICATION_VERIFICATION); + } + } +*/ + + X509_free (cert); + return (SSL_get_verify_result(request->ssl)); +} + + +int +gftp_ssl_startup (gftp_request * request) +{ + gftp_ssl_initialized = 1; + + /* FIXME _ thread setup */ + /* FIXME - only call this from one place */ + if (!SSL_library_init ()) + { + if (request != NULL) + request->logging_function (gftp_logging_error, request->user_data, + _("Cannot initialized the OpenSSL library\n")); + return (GFTP_EFATAL); + } + + SSL_load_error_strings (); + RAND_load_file ("/dev/urandom", 1024); /* FIXME - be able to specify this file */ + + ctx = SSL_CTX_new (SSLv23_method ()); + + if (SSL_CTX_set_default_verify_paths (ctx) != 1) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error loading default SSL certificates\n")); + return (GFTP_EFATAL); + } + + SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER, gftp_ssl_verify_callback); + SSL_CTX_set_verify_depth (ctx, 4); + SSL_CTX_set_options (ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2); + + if (SSL_CTX_set_cipher_list (ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error setting cipher list (no valid ciphers)\n")); + return (GFTP_EFATAL); + } + + + return (0); +} + + +int +gftp_ssl_session_setup (gftp_request * request) +{ + BIO * bio; + long ret; + + g_return_val_if_fail (request->sockfd > 0, GFTP_EFATAL); + + if (!gftp_ssl_initialized) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error: SSL engine was not initialized\n")); + return (GFTP_EFATAL); + } + + if (gftp_fd_set_sockblocking (request, request->sockfd, 0) < 0) /* FIXME */ + { + gftp_disconnect (request); + return (GFTP_ERETRYABLE); + } + + if ((bio = BIO_new (BIO_s_socket ())) == NULL) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error setting up SSL connection (BIO object)\n")); + return (GFTP_EFATAL); + } + + BIO_set_fd (bio, request->sockfd, BIO_NOCLOSE); + + if ((request->ssl = SSL_new (ctx)) == NULL) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error setting up SSL connection (SSL object)\n")); + return (GFTP_EFATAL); + } + + SSL_set_bio (request->ssl, bio, bio); + + if (SSL_connect (request->ssl) <= 0) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error connecting to SSL object\n")); + return (GFTP_EFATAL); + } + + if ((ret = gftp_ssl_post_connection_check (request)) != X509_V_OK) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error with peer certificate: %s\n"), + X509_verify_cert_error_string (ret)); + return (GFTP_EFATAL); + } + + request->logging_function (gftp_logging_misc, request->user_data, + "SSL connection established using %s (%s)\n", + SSL_get_cipher_version (request->ssl), + SSL_get_cipher_name (request->ssl)); + + return (0); +} + + +ssize_t +gftp_ssl_read (gftp_request * request, void *ptr, size_t size, int fd) +{ + ssize_t ret; + int err; + + if (!gftp_ssl_initialized) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error: SSL engine was not initialized\n")); + return (GFTP_EFATAL); + } + + errno = 0; + ret = 0; + do + { + if ((ret = SSL_read (request->ssl, ptr, size)) < 0) + { + err = SSL_get_error (request->ssl, ret); + printf ("error is %d\n", err); + if (errno == EINTR) + { + if (request != NULL && request->cancel) + break; + else + continue; + } + + if (request != NULL) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error: Could not read from socket: %s\n"), + g_strerror (errno)); + gftp_disconnect (request); + } + return (GFTP_ERETRYABLE); + } + } + while (errno == EINTR && !(request != NULL && request->cancel)); + + if (errno == EINTR && request != NULL && request->cancel) + { + gftp_disconnect (request); + return (GFTP_ERETRYABLE); + } + + return (ret); +} + + +ssize_t +gftp_ssl_write (gftp_request * request, const char *ptr, size_t size, int fd) +{ + size_t ret, w_ret; + + if (!gftp_ssl_initialized) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error: SSL engine was not initialized\n")); + return (GFTP_EFATAL); + } + + ret = 0; + do + { + w_ret = SSL_write (request->ssl, ptr, size); + if (w_ret <= 0) + { + if (errno == EINTR) + { + if (request != NULL && request->cancel) + break; + else + continue; + } + + if (request != NULL) + { + request->logging_function (gftp_logging_error, request->user_data, + _("Error: Could not write to socket: %s\n"), + g_strerror (errno)); + gftp_disconnect (request); + } + return (GFTP_ERETRYABLE); + } + ptr += w_ret; + size -= w_ret; + ret += w_ret; + } + while (size > 0); + + if (errno == EINTR && request != NULL && request->cancel) + { + gftp_disconnect (request); + return (GFTP_ERETRYABLE); + } + + return (ret); +} + +#endif
--- a/src/gtk/bookmarks.c Wed May 28 18:37:28 2003 +0000 +++ b/src/gtk/bookmarks.c Sun Jun 08 15:04:40 2003 +0000 @@ -879,7 +879,7 @@ { gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (dialog->window, gftp_version); } tempwid = gtk_frame_new (NULL); @@ -1259,7 +1259,7 @@ { gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (dialog->window, gftp_version); } /* FIXME - memory leak */
--- a/src/gtk/chmod_dialog.c Wed May 28 18:37:28 2003 +0000 +++ b/src/gtk/chmod_dialog.c Sun Jun 08 15:04:40 2003 +0000 @@ -183,7 +183,7 @@ { gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (dialog->window, gftp_version); } tempwid = gtk_label_new (_("You can now adjust the attributes of your file(s)\nNote: Not all ftp servers support the chmod feature"));
--- a/src/gtk/gftp-gtk.c Wed May 28 18:37:28 2003 +0000 +++ b/src/gtk/gftp-gtk.c Sun Jun 08 15:04:40 2003 +0000 @@ -1096,7 +1096,7 @@ { gdk_window_set_icon (window->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (window->window, _("gFTP Icon")); + gdk_window_set_icon_name (window->window, gftp_version); } other_wdata = &window1;
--- a/src/gtk/menu-items.c Wed May 28 18:37:28 2003 +0000 +++ b/src/gtk/menu-items.c Sun Jun 08 15:04:40 2003 +0000 @@ -756,7 +756,7 @@ { gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (dialog->window, gftp_version); } notebook = gtk_notebook_new ();
--- a/src/gtk/misc-gtk.c Wed May 28 18:37:28 2003 +0000 +++ b/src/gtk/misc-gtk.c Sun Jun 08 15:04:40 2003 +0000 @@ -523,9 +523,9 @@ } +/* FIXME - check this */ static gchar * -gftp_item_factory_translate (const char *path, - gpointer func_data) +gftp_item_factory_translate (const char *path, gpointer func_data) { const gchar *strip_prefix = func_data; const char *result; @@ -535,7 +535,7 @@ char *tmp_path = g_strconcat (strip_prefix, path, NULL); result = gettext (tmp_path); if (result == tmp_path) - result = path; + result = path; g_free (tmp_path); } else @@ -946,7 +946,7 @@ { gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (dialog->window, gftp_version); } ddata->dialog = dialog; @@ -1070,7 +1070,7 @@ { gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (dialog->window, gftp_version); } ddata->dialog = dialog;
--- a/src/gtk/options_dialog.c Wed May 28 18:37:28 2003 +0000 +++ b/src/gtk/options_dialog.c Sun Jun 08 15:04:40 2003 +0000 @@ -1203,7 +1203,7 @@ { gdk_window_set_icon (option_data.dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (option_data.dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (option_data.dialog->window, gftp_version); } option_data.notebook = gtk_notebook_new ();
--- a/src/gtk/view_dialog.c Wed May 28 18:37:28 2003 +0000 +++ b/src/gtk/view_dialog.c Sun Jun 08 15:04:40 2003 +0000 @@ -327,7 +327,7 @@ { gdk_window_set_icon (dialog->window, NULL, gftp_icon->pixmap, gftp_icon->bitmap); - gdk_window_set_icon_name (dialog->window, _("gFTP Icon")); + gdk_window_set_icon_name (dialog->window, gftp_version); } table = gtk_table_new (1, 2, FALSE);