Thomas J. Moore provided a patch that introduces Kerberos5 support in
libcurl. This also makes the options change name to --krb (from --krb4) and CURLOPT_KRBLEVEL (from CURLOPT_KRB4LEVEL) but the old names are still
This commit is contained in:
parent
667fd9a60b
commit
54967d2a3a
4
CHANGES
4
CHANGES
@ -7,6 +7,10 @@
|
|||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
Daniel S (1 July 2007)
|
Daniel S (1 July 2007)
|
||||||
|
- Thomas J. Moore provided a patch that introduces Kerberos5 support in
|
||||||
|
libcurl. This also makes the options change name to --krb (from --krb4) and
|
||||||
|
CURLOPT_KRBLEVEL (from CURLOPT_KRB4LEVEL) but the old names are still
|
||||||
|
|
||||||
- Song Ma helped me verify and extend a fix for doing FTP over a SOCKS4/5
|
- Song Ma helped me verify and extend a fix for doing FTP over a SOCKS4/5
|
||||||
proxy.
|
proxy.
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ This release includes the following changes:
|
|||||||
|
|
||||||
o added CURLOPT_NEW_FILE_PERMS and CURLOPT_NEW_DIRECTORY_PERMS
|
o added CURLOPT_NEW_FILE_PERMS and CURLOPT_NEW_DIRECTORY_PERMS
|
||||||
o improved hashing of sockets for the multi_socket API
|
o improved hashing of sockets for the multi_socket API
|
||||||
|
o ftp kerberos5 support added
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ New curl mirrors:
|
|||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Robert Iakobashvili, James Housley, Günter Knauf, James Bursa, Song Ma
|
Robert Iakobashvili, James Housley, Günter Knauf, James Bursa, Song Ma,
|
||||||
|
Thomas J. Moore
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
@ -73,7 +73,7 @@ HTTPS (*1)
|
|||||||
FTP
|
FTP
|
||||||
- download
|
- download
|
||||||
- authentication
|
- authentication
|
||||||
- kerberos4 (*5)
|
- kerberos4 (*5), kerberos5 (*3)
|
||||||
- active/passive using PORT, EPRT, PASV or EPSV
|
- active/passive using PORT, EPRT, PASV or EPSV
|
||||||
- single file size information (compare to HTTP HEAD)
|
- single file size information (compare to HTTP HEAD)
|
||||||
- 'type=' URL support
|
- 'type=' URL support
|
||||||
|
15
docs/MANUAL
15
docs/MANUAL
@ -809,18 +809,19 @@ CUSTOM OUTPUT
|
|||||||
|
|
||||||
curl -w 'We downloaded %{size_download} bytes\n' www.download.com
|
curl -w 'We downloaded %{size_download} bytes\n' www.download.com
|
||||||
|
|
||||||
KERBEROS4 FTP TRANSFER
|
KERBEROS FTP TRANSFER
|
||||||
|
|
||||||
Curl supports kerberos4 for FTP transfers. You need the kerberos package
|
Curl supports kerberos4 and kerberos5/GSSAPI for FTP transfers. You need
|
||||||
installed and used at curl build time for it to be used.
|
the kerberos package installed and used at curl build time for it to be
|
||||||
|
used.
|
||||||
|
|
||||||
First, get the krb-ticket the normal way, like with the kauth tool. Then use
|
First, get the krb-ticket the normal way, like with the kinit/kauth tool.
|
||||||
curl in way similar to:
|
Then use curl in way similar to:
|
||||||
|
|
||||||
curl --krb4 private ftp://krb4site.com -u username:fakepwd
|
curl --krb private ftp://krb4site.com -u username:fakepwd
|
||||||
|
|
||||||
There's no use for a password on the -u switch, but a blank one will make
|
There's no use for a password on the -u switch, but a blank one will make
|
||||||
curl ask for one and you already entered the real password to kauth.
|
curl ask for one and you already entered the real password to kinit/kauth.
|
||||||
|
|
||||||
TELNET
|
TELNET
|
||||||
|
|
||||||
|
11
docs/curl.1
11
docs/curl.1
@ -593,13 +593,14 @@ private key is. DER, PEM and ENG are supported. If not specified, PEM is
|
|||||||
assumed.
|
assumed.
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "--krb4 <level>"
|
.IP "--krb <level>"
|
||||||
(FTP) Enable Kerberos4 authentication and use. The level must be entered and
|
(FTP) Enable Kerberos authentication and use. The level must be entered and
|
||||||
should be one of 'clear', 'safe', 'confidential' or 'private'. Should you use
|
should be one of 'clear', 'safe', 'confidential' or 'private'. Should you use
|
||||||
a level that is not one of these, 'private' will instead be used.
|
a level that is not one of these, 'private' will instead be used.
|
||||||
|
|
||||||
This option requires that the library was built with Kerberos4 support. This
|
This option requires that the library was built with kerberos4 or GSSAPI
|
||||||
is not very common. Use \fI-V/--version\fP to see if your curl supports it.
|
(GSS-Negotiate) support. This is not very common. Use \fI-V/--version\fP to
|
||||||
|
see if your curl supports it.
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "-K/--config <config file>"
|
.IP "-K/--config <config file>"
|
||||||
@ -1153,7 +1154,7 @@ Automatic decompression of compressed files over HTTP is supported.
|
|||||||
.IP "NTLM"
|
.IP "NTLM"
|
||||||
NTLM authentication is supported.
|
NTLM authentication is supported.
|
||||||
.IP "GSS-Negotiate"
|
.IP "GSS-Negotiate"
|
||||||
Negotiate authentication is supported.
|
Negotiate authentication and krb5 for ftp is supported.
|
||||||
.IP "Debug"
|
.IP "Debug"
|
||||||
This curl uses a libcurl built with Debug. This enables more error-tracking
|
This curl uses a libcurl built with Debug. This enables more error-tracking
|
||||||
and memory debugging etc. For curl-developers only!
|
and memory debugging etc. For curl-developers only!
|
||||||
|
@ -1370,12 +1370,12 @@ this to 1 to enable it. By default all transfers are done using the
|
|||||||
cache. Note that while nothing ever should get hurt by attempting to reuse SSL
|
cache. Note that while nothing ever should get hurt by attempting to reuse SSL
|
||||||
session-IDs, there seem to be broken SSL implementations in the wild that may
|
session-IDs, there seem to be broken SSL implementations in the wild that may
|
||||||
require you to disable this in order for you to succeed. (Added in 7.16.0)
|
require you to disable this in order for you to succeed. (Added in 7.16.0)
|
||||||
.IP CURLOPT_KRB4LEVEL
|
.IP CURLOPT_KRBLEVEL
|
||||||
Pass a char * as parameter. Set the krb4 security level, this also enables
|
Pass a char * as parameter. Set the kerberos security level for FTP; this
|
||||||
krb4 awareness. This is a string, 'clear', 'safe', 'confidential' or
|
also enables kerberos awareness. This is a string, 'clear', 'safe',
|
||||||
\&'private'. If the string is set but doesn't match one of these, 'private'
|
'confidential' or \&'private'. If the string is set but doesn't match one
|
||||||
will be used. Set the string to NULL to disable Kerberos4. The Kerberos
|
of these, 'private' will be used. Set the string to NULL to disable kerberos
|
||||||
support only works for FTP.
|
support for FTP.
|
||||||
.SH SSH OPTIONS
|
.SH SSH OPTIONS
|
||||||
.IP CURLOPT_SSH_AUTH_TYPES
|
.IP CURLOPT_SSH_AUTH_TYPES
|
||||||
Pass a long set to a bitmask consisting of one or more of
|
Pass a long set to a bitmask consisting of one or more of
|
||||||
|
@ -736,10 +736,12 @@ typedef enum {
|
|||||||
/* Set the interface string to use as outgoing network interface */
|
/* Set the interface string to use as outgoing network interface */
|
||||||
CINIT(INTERFACE, OBJECTPOINT, 62),
|
CINIT(INTERFACE, OBJECTPOINT, 62),
|
||||||
|
|
||||||
/* Set the krb4 security level, this also enables krb4 awareness. This is a
|
/* Set the krb4/5 security level, this also enables krb4/5 awareness. This
|
||||||
* string, 'clear', 'safe', 'confidential' or 'private'. If the string is
|
* is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
|
||||||
* set but doesn't match one of these, 'private' will be used. */
|
* is set but doesn't match one of these, 'private' will be used. */
|
||||||
CINIT(KRB4LEVEL, OBJECTPOINT, 63),
|
CINIT(KRBLEVEL, OBJECTPOINT, 63),
|
||||||
|
/* This is for compatibility with older curl releases */
|
||||||
|
#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
|
||||||
|
|
||||||
/* Set if we should verify the peer in ssl handshake, set 1 to verify. */
|
/* Set if we should verify the peer in ssl handshake, set 1 to verify. */
|
||||||
CINIT(SSL_VERIFYPEER, LONG, 64),
|
CINIT(SSL_VERIFYPEER, LONG, 64),
|
||||||
|
@ -4,6 +4,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
|||||||
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
|
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
|
||||||
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \
|
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \
|
||||||
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
|
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
|
||||||
|
krb5.c \
|
||||||
memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \
|
memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \
|
||||||
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
||||||
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
||||||
|
97
lib/ftp.c
97
lib/ftp.c
@ -75,7 +75,7 @@
|
|||||||
#include "socks.h"
|
#include "socks.h"
|
||||||
#include "ftp.h"
|
#include "ftp.h"
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
#include "krb4.h"
|
#include "krb4.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -319,8 +319,17 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
|||||||
ftpc->cache_size = 0; /* zero the size just in case */
|
ftpc->cache_size = 0; /* zero the size just in case */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int res = Curl_read(conn, sockfd, ptr, BUFSIZE-ftpc->nread_resp,
|
int res;
|
||||||
&gotbytes);
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
enum protection_level prot = conn->data_prot;
|
||||||
|
|
||||||
|
conn->data_prot = 0;
|
||||||
|
#endif
|
||||||
|
res = Curl_read(conn, sockfd, ptr, BUFSIZE-ftpc->nread_resp,
|
||||||
|
&gotbytes);
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
conn->data_prot = prot;
|
||||||
|
#endif
|
||||||
if(res < 0)
|
if(res < 0)
|
||||||
/* EWOULDBLOCK */
|
/* EWOULDBLOCK */
|
||||||
return CURLE_OK; /* return */
|
return CURLE_OK; /* return */
|
||||||
@ -360,6 +369,9 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
|||||||
the line isn't really terminated until the LF comes */
|
the line isn't really terminated until the LF comes */
|
||||||
|
|
||||||
/* output debug output if that is requested */
|
/* output debug output if that is requested */
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
if(!conn->sec_complete)
|
||||||
|
#endif
|
||||||
if(data->set.verbose)
|
if(data->set.verbose)
|
||||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||||
ftpc->linestart_resp, (size_t)perline, conn);
|
ftpc->linestart_resp, (size_t)perline, conn);
|
||||||
@ -414,18 +426,18 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
|
|||||||
if(!result)
|
if(!result)
|
||||||
code = atoi(buf);
|
code = atoi(buf);
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
/* handle the security-oriented responses 6xx ***/
|
/* handle the security-oriented responses 6xx ***/
|
||||||
/* FIXME: some errorchecking perhaps... ***/
|
/* FIXME: some errorchecking perhaps... ***/
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case 631:
|
case 631:
|
||||||
Curl_sec_read_msg(conn, buf, prot_safe);
|
code = Curl_sec_read_msg(conn, buf, prot_safe);
|
||||||
break;
|
break;
|
||||||
case 632:
|
case 632:
|
||||||
Curl_sec_read_msg(conn, buf, prot_private);
|
code = Curl_sec_read_msg(conn, buf, prot_private);
|
||||||
break;
|
break;
|
||||||
case 633:
|
case 633:
|
||||||
Curl_sec_read_msg(conn, buf, prot_confidential);
|
code = Curl_sec_read_msg(conn, buf, prot_confidential);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* normal ftp stuff we pass through! */
|
/* normal ftp stuff we pass through! */
|
||||||
@ -553,7 +565,17 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
|||||||
ftpc->cache_size = 0; /* zero the size just in case */
|
ftpc->cache_size = 0; /* zero the size just in case */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp, &gotbytes);
|
int res;
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
enum protection_level prot = conn->data_prot;
|
||||||
|
|
||||||
|
conn->data_prot = 0;
|
||||||
|
#endif
|
||||||
|
res = Curl_read(conn, sockfd, ptr, BUFSIZE-*nreadp,
|
||||||
|
&gotbytes);
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
conn->data_prot = prot;
|
||||||
|
#endif
|
||||||
if(res < 0)
|
if(res < 0)
|
||||||
/* EWOULDBLOCK */
|
/* EWOULDBLOCK */
|
||||||
continue; /* go looping again */
|
continue; /* go looping again */
|
||||||
@ -593,6 +615,9 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
|||||||
the line isn't really terminated until the LF comes */
|
the line isn't really terminated until the LF comes */
|
||||||
|
|
||||||
/* output debug output if that is requested */
|
/* output debug output if that is requested */
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
if(!conn->sec_complete)
|
||||||
|
#endif
|
||||||
if(data->set.verbose)
|
if(data->set.verbose)
|
||||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||||
line_start, (size_t)perline, conn);
|
line_start, (size_t)perline, conn);
|
||||||
@ -646,18 +671,18 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
|
|||||||
if(!result)
|
if(!result)
|
||||||
code = atoi(buf);
|
code = atoi(buf);
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
/* handle the security-oriented responses 6xx ***/
|
/* handle the security-oriented responses 6xx ***/
|
||||||
/* FIXME: some errorchecking perhaps... ***/
|
/* FIXME: some errorchecking perhaps... ***/
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case 631:
|
case 631:
|
||||||
Curl_sec_read_msg(conn, buf, prot_safe);
|
code = Curl_sec_read_msg(conn, buf, prot_safe);
|
||||||
break;
|
break;
|
||||||
case 632:
|
case 632:
|
||||||
Curl_sec_read_msg(conn, buf, prot_private);
|
code = Curl_sec_read_msg(conn, buf, prot_private);
|
||||||
break;
|
break;
|
||||||
case 633:
|
case 633:
|
||||||
Curl_sec_read_msg(conn, buf, prot_confidential);
|
code = Curl_sec_read_msg(conn, buf, prot_confidential);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* normal ftp stuff we pass through! */
|
/* normal ftp stuff we pass through! */
|
||||||
@ -2299,14 +2324,7 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
|
|||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#ifdef HAVE_KRB4
|
||||||
if(conn->data->set.krb4) {
|
if(conn->data->set.krb) {
|
||||||
/* We are logged in, asked to use Kerberos. Set the requested
|
|
||||||
* protection level
|
|
||||||
*/
|
|
||||||
if(conn->sec_complete)
|
|
||||||
/* BLOCKING */
|
|
||||||
Curl_sec_set_protection_level(conn);
|
|
||||||
|
|
||||||
/* We may need to issue a KAUTH here to have access to the files
|
/* We may need to issue a KAUTH here to have access to the files
|
||||||
* do it if user supplied a password
|
* do it if user supplied a password
|
||||||
*/
|
*/
|
||||||
@ -2353,7 +2371,8 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
|
|||||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||||
(void)instate; /* no use for this yet */
|
(void)instate; /* no use for this yet */
|
||||||
|
|
||||||
if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
|
/* some need password anyway, and others just return 2xx ignored */
|
||||||
|
if((ftpcode == 331 || ftpcode/100 == 2) && (ftpc->state == FTP_USER)) {
|
||||||
/* 331 Password required for ...
|
/* 331 Password required for ...
|
||||||
(the server requires to send the user's password too) */
|
(the server requires to send the user's password too) */
|
||||||
NBFTPSENDF(conn, "PASS %s", ftp->passwd?ftp->passwd:"");
|
NBFTPSENDF(conn, "PASS %s", ftp->passwd?ftp->passwd:"");
|
||||||
@ -2461,15 +2480,15 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We have received a 220 response fine, now we proceed. */
|
/* We have received a 220 response fine, now we proceed. */
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
if(data->set.krb4) {
|
if(data->set.krb) {
|
||||||
/* If not anonymous login, try a secure login. Note that this
|
/* If not anonymous login, try a secure login. Note that this
|
||||||
procedure is still BLOCKING. */
|
procedure is still BLOCKING. */
|
||||||
|
|
||||||
Curl_sec_request_prot(conn, "private");
|
Curl_sec_request_prot(conn, "private");
|
||||||
/* We set private first as default, in case the line below fails to
|
/* We set private first as default, in case the line below fails to
|
||||||
set a valid level */
|
set a valid level */
|
||||||
Curl_sec_request_prot(conn, data->set.krb4_level);
|
Curl_sec_request_prot(conn, data->set.krb_level);
|
||||||
|
|
||||||
if(Curl_sec_login(conn) != 0)
|
if(Curl_sec_login(conn) != 0)
|
||||||
infof(data, "Logging in with password in cleartext!\n");
|
infof(data, "Logging in with password in cleartext!\n");
|
||||||
@ -3086,7 +3105,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, bool premature
|
|||||||
/* free the dir tree and file parts */
|
/* free the dir tree and file parts */
|
||||||
freedirs(conn);
|
freedirs(conn);
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
|
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3496,16 +3515,21 @@ CURLcode Curl_nbftpsendf(struct connectdata *conn,
|
|||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
ssize_t bytes_written;
|
ssize_t bytes_written;
|
||||||
char s[256];
|
/* may still not be big enough for some krb5 tokens */
|
||||||
|
#define SBUF_SIZE 1024
|
||||||
|
char s[SBUF_SIZE];
|
||||||
size_t write_len;
|
size_t write_len;
|
||||||
char *sptr=s;
|
char *sptr=s;
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
enum protection_level data_sec = conn->data_prot;
|
||||||
|
#endif
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(s, 250, fmt, ap);
|
vsnprintf(s, SBUF_SIZE-3, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
strcat(s, "\r\n"); /* append a trailing CRLF */
|
strcat(s, "\r\n"); /* append a trailing CRLF */
|
||||||
@ -3523,8 +3547,14 @@ CURLcode Curl_nbftpsendf(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif /* CURL_DOES_CONVERSIONS */
|
#endif /* CURL_DOES_CONVERSIONS */
|
||||||
|
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
conn->data_prot = prot_cmd;
|
||||||
|
#endif
|
||||||
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||||
&bytes_written);
|
&bytes_written);
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
conn->data_prot = data_sec;
|
||||||
|
#endif
|
||||||
|
|
||||||
if(CURLE_OK != res)
|
if(CURLE_OK != res)
|
||||||
return res;
|
return res;
|
||||||
@ -3557,14 +3587,17 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
|||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
ssize_t bytes_written;
|
ssize_t bytes_written;
|
||||||
char s[256];
|
char s[SBUF_SIZE];
|
||||||
size_t write_len;
|
size_t write_len;
|
||||||
char *sptr=s;
|
char *sptr=s;
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
enum protection_level data_sec = conn->data_prot;
|
||||||
|
#endif
|
||||||
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsnprintf(s, 250, fmt, ap);
|
vsnprintf(s, SBUF_SIZE-3, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
strcat(s, "\r\n"); /* append a trailing CRLF */
|
strcat(s, "\r\n"); /* append a trailing CRLF */
|
||||||
@ -3581,8 +3614,14 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
|
|||||||
#endif /* CURL_DOES_CONVERSIONS */
|
#endif /* CURL_DOES_CONVERSIONS */
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
conn->data_prot = prot_cmd;
|
||||||
|
#endif
|
||||||
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
res = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
|
||||||
&bytes_written);
|
&bytes_written);
|
||||||
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
conn->data_prot = data_sec;
|
||||||
|
#endif
|
||||||
|
|
||||||
if(CURLE_OK != res)
|
if(CURLE_OK != res)
|
||||||
break;
|
break;
|
||||||
|
@ -575,6 +575,8 @@ void Curl_freeaddrinfo(Curl_addrinfo *ai)
|
|||||||
/* walk over the list and free all entries */
|
/* walk over the list and free all entries */
|
||||||
while(ai) {
|
while(ai) {
|
||||||
next = ai->ai_next;
|
next = ai->ai_next;
|
||||||
|
if(ai->ai_canonname)
|
||||||
|
free(ai->ai_canonname);
|
||||||
free(ai);
|
free(ai);
|
||||||
ai = next;
|
ai = next;
|
||||||
}
|
}
|
||||||
|
@ -380,6 +380,9 @@ Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port)
|
|||||||
and use that area to store the address */
|
and use that area to store the address */
|
||||||
ai->ai_addr = (struct sockaddr *) ((char*)ai + sizeof(Curl_addrinfo));
|
ai->ai_addr = (struct sockaddr *) ((char*)ai + sizeof(Curl_addrinfo));
|
||||||
|
|
||||||
|
/* FIXME: need to free this eventually */
|
||||||
|
ai->ai_canonname = strdup(he->h_name);
|
||||||
|
|
||||||
/* leave the rest of the struct filled with zero */
|
/* leave the rest of the struct filled with zero */
|
||||||
|
|
||||||
addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */
|
addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */
|
||||||
|
@ -279,9 +279,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
/* the given address is numerical only, prevent a reverse lookup */
|
/* the given address is numerical only, prevent a reverse lookup */
|
||||||
hints.ai_flags = AI_NUMERICHOST;
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
}
|
}
|
||||||
#if 0 /* removed nov 8 2005 before 7.15.1 */
|
#ifdef HAVE_GSSAPI
|
||||||
else
|
if(conn->data->set.krb)
|
||||||
hints.ai_flags = AI_CANONNAME;
|
/* if krb is used, we (might) need the canonical host name */
|
||||||
|
hints.ai_flags |= AI_CANONNAME;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(port) {
|
if(port) {
|
||||||
|
@ -40,7 +40,12 @@ struct Curl_sec_client_mech {
|
|||||||
#define AUTH_CONTINUE 1
|
#define AUTH_CONTINUE 1
|
||||||
#define AUTH_ERROR 2
|
#define AUTH_ERROR 2
|
||||||
|
|
||||||
|
#ifdef HAVE_KRB4
|
||||||
extern struct Curl_sec_client_mech Curl_krb4_client_mech;
|
extern struct Curl_sec_client_mech Curl_krb4_client_mech;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
extern struct Curl_sec_client_mech Curl_krb5_client_mech;
|
||||||
|
#endif
|
||||||
|
|
||||||
CURLcode Curl_krb_kauth(struct connectdata *conn);
|
CURLcode Curl_krb_kauth(struct connectdata *conn);
|
||||||
int Curl_sec_fflush_fd(struct connectdata *conn, int fd);
|
int Curl_sec_fflush_fd(struct connectdata *conn, int fd);
|
||||||
|
316
lib/krb5.c
Normal file
316
lib/krb5.c
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
/* This source code was modified by Martin Hedenfalk <mhe@stacken.kth.se> for
|
||||||
|
* use in Curl. His latest changes were done 2000-09-18.
|
||||||
|
*
|
||||||
|
* It has since been patched away like a madman by Daniel Stenberg
|
||||||
|
* <daniel@haxx.se> to make it better applied to curl conditions, and to make
|
||||||
|
* it not use globals, pollute name space and more. This source code awaits a
|
||||||
|
* rewrite to work around the paragraph 2 in the BSD licenses as explained
|
||||||
|
* below.
|
||||||
|
*
|
||||||
|
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
|
||||||
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the Institute nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE. */
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#ifndef CURL_DISABLE_FTP
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#include <string.h>
|
||||||
|
#include <gssapi/gssapi.h>
|
||||||
|
#include <gssapi/gssapi_generic.h>
|
||||||
|
#include <gssapi/gssapi_krb5.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h> /* for getpid() */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include "base64.h"
|
||||||
|
#include "ftp.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "krb4.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||||
|
#include "inet_ntoa_r.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
#define LOCAL_ADDR (&conn->local_addr)
|
||||||
|
#define REMOTE_ADDR conn->ip_addr->ai_addr
|
||||||
|
#define myctladdr LOCAL_ADDR
|
||||||
|
#define hisctladdr REMOTE_ADDR
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb5_check_prot(void *app_data, int level)
|
||||||
|
{
|
||||||
|
gss_ctx_id_t *context = app_data;
|
||||||
|
app_data = NULL; /* prevent compiler warning */
|
||||||
|
if(level == prot_confidential)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb5_decode(void *app_data, void *buf, int len, int level,
|
||||||
|
struct connectdata *conn)
|
||||||
|
{
|
||||||
|
gss_ctx_id_t *context = app_data;
|
||||||
|
OM_uint32 maj, min;
|
||||||
|
gss_buffer_desc enc, dec;
|
||||||
|
|
||||||
|
enc.value = buf;
|
||||||
|
enc.length = len;
|
||||||
|
maj = gss_unseal(&min, *context, &enc, &dec, NULL, NULL);
|
||||||
|
if(maj != GSS_S_COMPLETE) {
|
||||||
|
if(len >= 4)
|
||||||
|
strcpy(buf, "599 ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, dec.value, dec.length);
|
||||||
|
len = dec.length;
|
||||||
|
gss_release_buffer(&min, &dec);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb5_overhead(void *app_data, int level, int len)
|
||||||
|
{
|
||||||
|
gss_ctx_id_t *context = app_data;
|
||||||
|
/* no arguments are used, just init them to prevent compiler warnings */
|
||||||
|
app_data = NULL;
|
||||||
|
level = 0;
|
||||||
|
len = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb5_encode(void *app_data, void *from, int length, int level, void **to,
|
||||||
|
struct connectdata *conn)
|
||||||
|
{
|
||||||
|
gss_ctx_id_t *context = app_data;
|
||||||
|
gss_buffer_desc dec, enc;
|
||||||
|
OM_uint32 maj, min;
|
||||||
|
int state;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
dec.value = from;
|
||||||
|
dec.length = length;
|
||||||
|
maj = gss_seal(&min, *context,
|
||||||
|
level == prot_private,
|
||||||
|
GSS_C_QOP_DEFAULT,
|
||||||
|
&dec, &state, &enc);
|
||||||
|
|
||||||
|
if(maj != GSS_S_COMPLETE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* malloc a new buffer, in case gss_release_buffer doesn't work as expected */
|
||||||
|
*to = malloc(enc.length);
|
||||||
|
if(!*to)
|
||||||
|
return -1;
|
||||||
|
memcpy(*to, enc.value, enc.length);
|
||||||
|
len = enc.length;
|
||||||
|
gss_release_buffer(&min, &enc);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb5_auth(void *app_data, struct connectdata *conn)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *p;
|
||||||
|
unsigned char *ptr;
|
||||||
|
size_t len;
|
||||||
|
u_int32_t cs;
|
||||||
|
const char *host = conn->dns_entry->addr->ai_canonname;
|
||||||
|
ssize_t nread;
|
||||||
|
unsigned int l = sizeof(conn->local_addr);
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
CURLcode result;
|
||||||
|
const char *service = "ftp", *srv_host = "host";
|
||||||
|
gss_buffer_desc gssbuf, _gssresp, *gssresp;
|
||||||
|
OM_uint32 maj, min;
|
||||||
|
gss_name_t gssname;
|
||||||
|
gss_ctx_id_t *context = app_data;
|
||||||
|
struct gss_channel_bindings_struct chan;
|
||||||
|
|
||||||
|
if(getsockname(conn->sock[FIRSTSOCKET],
|
||||||
|
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
|
||||||
|
perror("getsockname()");
|
||||||
|
|
||||||
|
chan.initiator_addrtype = GSS_C_AF_INET;
|
||||||
|
chan.initiator_address.length = l - 4;
|
||||||
|
chan.initiator_address.value = &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr;
|
||||||
|
chan.acceptor_addrtype = GSS_C_AF_INET;
|
||||||
|
chan.acceptor_address.length = l - 4;
|
||||||
|
chan.acceptor_address.value = &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr;
|
||||||
|
chan.application_data.length = 0;
|
||||||
|
chan.application_data.value = NULL;
|
||||||
|
|
||||||
|
/* this loop will execute twice (once for service, once for host) */
|
||||||
|
while(1) {
|
||||||
|
/* this really shouldn't be repeated here, but can't help it */
|
||||||
|
if(service == srv_host) {
|
||||||
|
result = Curl_ftpsendf(conn, "AUTH GSSAPI");
|
||||||
|
|
||||||
|
if(result)
|
||||||
|
return -2;
|
||||||
|
if(Curl_GetFTPResponse(&nread, conn, NULL))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(data->state.buffer[0] != '3')
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gssbuf.value = data->state.buffer;
|
||||||
|
gssbuf.length = snprintf(gssbuf.value, BUFSIZE, "%s@%s", service, host);
|
||||||
|
maj = gss_import_name(&min, &gssbuf, gss_nt_service_name, &gssname);
|
||||||
|
if(maj != GSS_S_COMPLETE) {
|
||||||
|
gss_release_name(&min, &gssname);
|
||||||
|
if(service == srv_host) {
|
||||||
|
Curl_failf(data, "Error importing service name %s", gssbuf.value);
|
||||||
|
return AUTH_ERROR;
|
||||||
|
}
|
||||||
|
service = srv_host;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
gss_OID t;
|
||||||
|
gss_display_name(&min, gssname, &gssbuf, &t);
|
||||||
|
Curl_infof(data, "Trying against %s\n", gssbuf.value);
|
||||||
|
gss_release_buffer(&min, &gssbuf);
|
||||||
|
}
|
||||||
|
gssresp = GSS_C_NO_BUFFER;
|
||||||
|
*context = GSS_C_NO_CONTEXT;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = AUTH_OK;
|
||||||
|
maj = gss_init_sec_context(&min,
|
||||||
|
GSS_C_NO_CREDENTIAL,
|
||||||
|
context,
|
||||||
|
gssname,
|
||||||
|
GSS_C_NO_OID,
|
||||||
|
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
|
||||||
|
0,
|
||||||
|
&chan,
|
||||||
|
gssresp,
|
||||||
|
NULL,
|
||||||
|
&gssbuf,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if(gssresp) {
|
||||||
|
free(_gssresp.value);
|
||||||
|
gssresp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
|
||||||
|
Curl_infof(data, "Error creating security context");
|
||||||
|
ret = AUTH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gssbuf.length != 0) {
|
||||||
|
if(Curl_base64_encode(data, (char *)gssbuf.value, gssbuf.length, &p) < 1) {
|
||||||
|
Curl_infof(data, "Out of memory base64-encoding");
|
||||||
|
ret = AUTH_CONTINUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = Curl_ftpsendf(conn, "ADAT %s", p);
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
if(result) {
|
||||||
|
ret = -2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Curl_GetFTPResponse(&nread, conn, NULL)) {
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){
|
||||||
|
Curl_infof(data, "Server didn't accept auth data\n");
|
||||||
|
ret = AUTH_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = data->state.buffer + 4;
|
||||||
|
p = strstr(p, "ADAT=");
|
||||||
|
if(p) {
|
||||||
|
_gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)&_gssresp.value);
|
||||||
|
if(_gssresp.length < 1) {
|
||||||
|
Curl_failf(data, "Out of memory base64-encoding");
|
||||||
|
ret = AUTH_CONTINUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gssresp = &_gssresp;
|
||||||
|
}
|
||||||
|
} while(maj == GSS_S_CONTINUE_NEEDED);
|
||||||
|
|
||||||
|
gss_release_name(&min, &gssname);
|
||||||
|
|
||||||
|
if(gssresp)
|
||||||
|
free(_gssresp.value);
|
||||||
|
|
||||||
|
if(ret == AUTH_OK || service == srv_host)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
service = srv_host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Curl_sec_client_mech Curl_krb5_client_mech = {
|
||||||
|
"GSSAPI",
|
||||||
|
sizeof(gss_ctx_id_t),
|
||||||
|
NULL, /* init */
|
||||||
|
krb5_auth,
|
||||||
|
NULL, /* end */
|
||||||
|
krb5_check_prot,
|
||||||
|
krb5_overhead,
|
||||||
|
krb5_encode,
|
||||||
|
krb5_decode
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* HAVE_GSSAPI */
|
||||||
|
#endif /* CURL_DISABLE_FTP */
|
@ -41,7 +41,7 @@
|
|||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
|
|
||||||
#ifndef CURL_DISABLE_FTP
|
#ifndef CURL_DISABLE_FTP
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
|
|
||||||
#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
|
#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
@ -87,8 +87,8 @@ name_to_level(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct Curl_sec_client_mech * const mechs[] = {
|
static const struct Curl_sec_client_mech * const mechs[] = {
|
||||||
#ifdef KRB5
|
#ifdef HAVE_GSSAPI
|
||||||
/* not supported */
|
&Curl_krb5_client_mech,
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_KRB4
|
#ifdef HAVE_KRB4
|
||||||
&Curl_krb4_client_mech,
|
&Curl_krb4_client_mech,
|
||||||
@ -118,6 +118,8 @@ block_read(int fd, void *buf, size_t len)
|
|||||||
b = read(fd, p, len);
|
b = read(fd, p, len);
|
||||||
if (b == 0)
|
if (b == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
else if (b < 0 && (errno == EINTR || errno == EAGAIN))
|
||||||
|
continue;
|
||||||
else if (b < 0)
|
else if (b < 0)
|
||||||
return -1;
|
return -1;
|
||||||
len -= b;
|
len -= b;
|
||||||
@ -133,7 +135,9 @@ block_write(int fd, void *buf, size_t len)
|
|||||||
int b;
|
int b;
|
||||||
while(len) {
|
while(len) {
|
||||||
b = write(fd, p, len);
|
b = write(fd, p, len);
|
||||||
if(b < 0)
|
if (b < 0 && (errno == EINTR || errno == EAGAIN))
|
||||||
|
continue;
|
||||||
|
else if(b < 0)
|
||||||
return -1;
|
return -1;
|
||||||
len -= b;
|
len -= b;
|
||||||
p += b;
|
p += b;
|
||||||
@ -155,7 +159,7 @@ sec_get_data(struct connectdata *conn,
|
|||||||
return -1;
|
return -1;
|
||||||
len = ntohl(len);
|
len = ntohl(len);
|
||||||
buf->data = realloc(buf->data, len);
|
buf->data = realloc(buf->data, len);
|
||||||
b = block_read(fd, buf->data, len);
|
b = buf->data ? block_read(fd, buf->data, len) : -1;
|
||||||
if (b == 0)
|
if (b == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (b < 0)
|
else if (b < 0)
|
||||||
@ -234,11 +238,36 @@ sec_send(struct connectdata *conn, int fd, char *from, int length)
|
|||||||
{
|
{
|
||||||
int bytes;
|
int bytes;
|
||||||
void *buf;
|
void *buf;
|
||||||
bytes = (conn->mech->encode)(conn->app_data, from, length, conn->data_prot,
|
enum protection_level protlevel = conn->data_prot;
|
||||||
|
int iscmd = protlevel == prot_cmd;
|
||||||
|
|
||||||
|
if(iscmd) {
|
||||||
|
if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5))
|
||||||
|
protlevel = prot_private;
|
||||||
|
else
|
||||||
|
protlevel = conn->command_prot;
|
||||||
|
}
|
||||||
|
bytes = (conn->mech->encode)(conn->app_data, from, length, protlevel,
|
||||||
&buf, conn);
|
&buf, conn);
|
||||||
bytes = htonl(bytes);
|
if(iscmd) {
|
||||||
block_write(fd, &bytes, sizeof(bytes));
|
char *cmdbuf;
|
||||||
block_write(fd, buf, ntohl(bytes));
|
|
||||||
|
bytes = Curl_base64_encode(conn->data, (char *)buf, bytes, &cmdbuf);
|
||||||
|
if(bytes > 0) {
|
||||||
|
if(protlevel == prot_private)
|
||||||
|
block_write(fd, "ENC ", 4);
|
||||||
|
else
|
||||||
|
block_write(fd, "MIC ", 4);
|
||||||
|
block_write(fd, cmdbuf, bytes);
|
||||||
|
block_write(fd, "\r\n", 2);
|
||||||
|
Curl_infof(conn->data, "%s %s\n", protlevel == prot_private ? "ENC" : "MIC", cmdbuf);
|
||||||
|
free(cmdbuf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes = htonl(bytes);
|
||||||
|
block_write(fd, &bytes, sizeof(bytes));
|
||||||
|
block_write(fd, buf, ntohl(bytes));
|
||||||
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
@ -267,6 +296,8 @@ Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length)
|
|||||||
return write(fd, buffer, length);
|
return write(fd, buffer, length);
|
||||||
|
|
||||||
len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len);
|
len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len);
|
||||||
|
if(len <= 0)
|
||||||
|
len = length;
|
||||||
while(length){
|
while(length){
|
||||||
if(length < len)
|
if(length < len)
|
||||||
len = length;
|
len = length;
|
||||||
@ -319,6 +350,11 @@ Curl_sec_read_msg(struct connectdata *conn, char *s, int level)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(conn->data->set.verbose) {
|
||||||
|
buf[len] = '\n';
|
||||||
|
Curl_debug(conn->data, CURLINFO_HEADER_IN, (char *)buf, len + 1, conn);
|
||||||
|
}
|
||||||
|
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
|
|
||||||
if(buf[3] == '-')
|
if(buf[3] == '-')
|
||||||
@ -360,7 +396,7 @@ sec_prot_internal(struct connectdata *conn, int level)
|
|||||||
if(Curl_GetFTPResponse(&nread, conn, &code))
|
if(Curl_GetFTPResponse(&nread, conn, &code))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(code/100 != '2'){
|
if(code/100 != 2){
|
||||||
failf(conn->data, "Failed to set protection buffer size.");
|
failf(conn->data, "Failed to set protection buffer size.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -385,6 +421,8 @@ sec_prot_internal(struct connectdata *conn, int level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
conn->data_prot = (enum protection_level)level;
|
conn->data_prot = (enum protection_level)level;
|
||||||
|
if(level == prot_private)
|
||||||
|
conn->command_prot = (enum protection_level)level;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,6 +506,9 @@ Curl_sec_login(struct connectdata *conn)
|
|||||||
conn->mech = *m;
|
conn->mech = *m;
|
||||||
conn->sec_complete = 1;
|
conn->sec_complete = 1;
|
||||||
conn->command_prot = prot_safe;
|
conn->command_prot = prot_safe;
|
||||||
|
/* Set the requested protection level */
|
||||||
|
/* BLOCKING */
|
||||||
|
Curl_sec_set_protection_level(conn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
#include "krb4.h"
|
#include "krb4.h"
|
||||||
#else
|
#else
|
||||||
#define Curl_sec_send(a,b,c,d) -1
|
#define Curl_sec_send(a,b,c,d) -1
|
||||||
@ -365,7 +365,7 @@ CURLcode Curl_write(struct connectdata *conn,
|
|||||||
bytes_written = Curl_sftp_send(conn, num, mem, len);
|
bytes_written = Curl_sftp_send(conn, num, mem, len);
|
||||||
#endif /* !USE_LIBSSH2 */
|
#endif /* !USE_LIBSSH2 */
|
||||||
else if(conn->sec_complete)
|
else if(conn->sec_complete)
|
||||||
/* only TRUE if krb4 enabled */
|
/* only TRUE if krb enabled */
|
||||||
bytes_written = Curl_sec_send(conn, num, mem, len);
|
bytes_written = Curl_sec_send(conn, num, mem, len);
|
||||||
else
|
else
|
||||||
bytes_written = Curl_plain_send(conn, num, mem, len);
|
bytes_written = Curl_plain_send(conn, num, mem, len);
|
||||||
|
11
lib/url.c
11
lib/url.c
@ -146,9 +146,6 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
|
|||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
|
||||||
#include "krb4.h"
|
|
||||||
#endif
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
@ -1498,12 +1495,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
*/
|
*/
|
||||||
data->set.localportrange = (int) va_arg(param, long);
|
data->set.localportrange = (int) va_arg(param, long);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_KRB4LEVEL:
|
case CURLOPT_KRBLEVEL:
|
||||||
/*
|
/*
|
||||||
* A string that defines the krb4 security level.
|
* A string that defines the kerberos security level.
|
||||||
*/
|
*/
|
||||||
data->set.krb4_level = va_arg(param, char *);
|
data->set.krb_level = va_arg(param, char *);
|
||||||
data->set.krb4 = (bool)(NULL != data->set.krb4_level);
|
data->set.krb = (bool)(NULL != data->set.krb_level);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_SSL_VERIFYPEER:
|
case CURLOPT_SSL_VERIFYPEER:
|
||||||
/*
|
/*
|
||||||
|
@ -133,8 +133,8 @@
|
|||||||
We prefix with CURL to prevent name collisions. */
|
We prefix with CURL to prevent name collisions. */
|
||||||
#define CURLMAX(x,y) ((x)>(y)?(x):(y))
|
#define CURLMAX(x,y) ((x)>(y)?(x):(y))
|
||||||
|
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
/* Types needed for krb4-ftp connections */
|
/* Types needed for krb4/5-ftp connections */
|
||||||
struct krb4buffer {
|
struct krb4buffer {
|
||||||
void *data;
|
void *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
@ -145,7 +145,8 @@ enum protection_level {
|
|||||||
prot_clear,
|
prot_clear,
|
||||||
prot_safe,
|
prot_safe,
|
||||||
prot_confidential,
|
prot_confidential,
|
||||||
prot_private
|
prot_private,
|
||||||
|
prot_cmd
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -882,8 +883,8 @@ struct connectdata {
|
|||||||
char *cookiehost; /* free later if not NULL */
|
char *cookiehost; /* free later if not NULL */
|
||||||
} allocptr;
|
} allocptr;
|
||||||
|
|
||||||
int sec_complete; /* if krb4 is enabled for this connection */
|
int sec_complete; /* if kerberos is enabled for this connection */
|
||||||
#ifdef HAVE_KRB4
|
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||||
enum protection_level command_prot;
|
enum protection_level command_prot;
|
||||||
enum protection_level data_prot;
|
enum protection_level data_prot;
|
||||||
enum protection_level request_data_prot;
|
enum protection_level request_data_prot;
|
||||||
@ -1277,7 +1278,7 @@ struct UserDefined {
|
|||||||
* to which to send the authorization data to, and no other
|
* to which to send the authorization data to, and no other
|
||||||
* host (which location-following otherwise could lead to)
|
* host (which location-following otherwise could lead to)
|
||||||
*/
|
*/
|
||||||
char *krb4_level; /* what security level */
|
char *krb_level; /* what security level */
|
||||||
struct ssl_config_data ssl; /* user defined SSL stuff */
|
struct ssl_config_data ssl; /* user defined SSL stuff */
|
||||||
|
|
||||||
curl_proxytype proxytype; /* what kind of proxy that is in use */
|
curl_proxytype proxytype; /* what kind of proxy that is in use */
|
||||||
@ -1331,7 +1332,7 @@ struct UserDefined {
|
|||||||
char *netrc_file; /* if not NULL, use this instead of trying to find
|
char *netrc_file; /* if not NULL, use this instead of trying to find
|
||||||
$HOME/.netrc */
|
$HOME/.netrc */
|
||||||
bool verbose;
|
bool verbose;
|
||||||
bool krb4; /* kerberos4 connection requested */
|
bool krb; /* kerberos connection requested */
|
||||||
bool reuse_forbid; /* forbidden to be reused, close after use */
|
bool reuse_forbid; /* forbidden to be reused, close after use */
|
||||||
bool reuse_fresh; /* do not re-use an existing connection */
|
bool reuse_fresh; /* do not re-use an existing connection */
|
||||||
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
|
bool ftp_use_epsv; /* if EPSV is to be attempted or not */
|
||||||
|
21
src/main.c
21
src/main.c
@ -411,7 +411,7 @@ struct Configurable {
|
|||||||
bool list_engines;
|
bool list_engines;
|
||||||
bool crlf;
|
bool crlf;
|
||||||
char *customrequest;
|
char *customrequest;
|
||||||
char *krb4level;
|
char *krblevel;
|
||||||
char *trace_dump; /* file to dump the network trace to, or NULL */
|
char *trace_dump; /* file to dump the network trace to, or NULL */
|
||||||
FILE *trace_stream;
|
FILE *trace_stream;
|
||||||
bool trace_fopened;
|
bool trace_fopened;
|
||||||
@ -665,7 +665,7 @@ static void help(void)
|
|||||||
" -I/--head Show document info only",
|
" -I/--head Show document info only",
|
||||||
" -j/--junk-session-cookies Ignore session cookies read from file (H)",
|
" -j/--junk-session-cookies Ignore session cookies read from file (H)",
|
||||||
" --interface <interface> Specify network interface/address to use",
|
" --interface <interface> Specify network interface/address to use",
|
||||||
" --krb4 <level> Enable krb4 with specified security level (F)",
|
" --krb <level> Enable kerberos with specified security level (F)",
|
||||||
" -k/--insecure Allow connections to SSL sites without certs (H)",
|
" -k/--insecure Allow connections to SSL sites without certs (H)",
|
||||||
" -K/--config Specify which config file to read",
|
" -K/--config Specify which config file to read",
|
||||||
" --libcurl <file> Dump libcurl equivalent code of this command line",
|
" --libcurl <file> Dump libcurl equivalent code of this command line",
|
||||||
@ -1476,7 +1476,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
{"*u", "crlf", FALSE},
|
{"*u", "crlf", FALSE},
|
||||||
{"*v", "stderr", TRUE},
|
{"*v", "stderr", TRUE},
|
||||||
{"*w", "interface", TRUE},
|
{"*w", "interface", TRUE},
|
||||||
{"*x", "krb4", TRUE},
|
{"*x", "krb" , TRUE},
|
||||||
|
{"*x", "krb4" , TRUE}, /* this is the previous name */
|
||||||
{"*y", "max-filesize", TRUE},
|
{"*y", "max-filesize", TRUE},
|
||||||
{"*z", "disable-eprt", FALSE},
|
{"*z", "disable-eprt", FALSE},
|
||||||
{"$a", "ftp-ssl", FALSE},
|
{"$a", "ftp-ssl", FALSE},
|
||||||
@ -1809,10 +1810,10 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
/* interface */
|
/* interface */
|
||||||
GetStr(&config->iface, nextarg);
|
GetStr(&config->iface, nextarg);
|
||||||
break;
|
break;
|
||||||
case 'x': /* --krb4 */
|
case 'x': /* --krb */
|
||||||
/* krb4 level string */
|
/* kerberos level string */
|
||||||
if(curlinfo->features & CURL_VERSION_KERBEROS4)
|
if(curlinfo->features & (CURL_VERSION_KERBEROS4 | CURL_VERSION_GSSNEGOTIATE))
|
||||||
GetStr(&config->krb4level, nextarg);
|
GetStr(&config->krblevel, nextarg);
|
||||||
else
|
else
|
||||||
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
||||||
break;
|
break;
|
||||||
@ -3260,8 +3261,8 @@ static void free_config_fields(struct Configurable *config)
|
|||||||
free(config->cookie);
|
free(config->cookie);
|
||||||
if(config->cookiefile)
|
if(config->cookiefile)
|
||||||
free(config->cookiefile);
|
free(config->cookiefile);
|
||||||
if(config->krb4level)
|
if(config->krblevel)
|
||||||
free(config->krb4level);
|
free(config->krblevel);
|
||||||
if(config->headerfile)
|
if(config->headerfile)
|
||||||
free(config->headerfile);
|
free(config->headerfile);
|
||||||
if(config->ftpport)
|
if(config->ftpport)
|
||||||
@ -4221,7 +4222,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
|||||||
/* three new ones in libcurl 7.3: */
|
/* three new ones in libcurl 7.3: */
|
||||||
my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
|
my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
|
||||||
my_setopt(curl, CURLOPT_INTERFACE, config->iface);
|
my_setopt(curl, CURLOPT_INTERFACE, config->iface);
|
||||||
my_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level);
|
my_setopt(curl, CURLOPT_KRBLEVEL, config->krblevel);
|
||||||
|
|
||||||
progressbarinit(&progressbar, config);
|
progressbarinit(&progressbar, config);
|
||||||
if((config->progressmode == CURL_PROGRESS_BAR) &&
|
if((config->progressmode == CURL_PROGRESS_BAR) &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user