Skip to content

Commit

Permalink
Thomas J. Moore provided a patch that introduces Kerberos5 support in
Browse files Browse the repository at this point in the history
libcurl. This also makes the options change name to --krb (from --krb4) and
CURLOPT_KRBLEVEL (from CURLOPT_KRB4LEVEL) but the old names are still
  • Loading branch information
bagder committed Jul 1, 2007
1 parent 667fd9a commit 54967d2
Show file tree
Hide file tree
Showing 19 changed files with 509 additions and 92 deletions.
4 changes: 4 additions & 0 deletions CHANGES
Expand Up @@ -7,6 +7,10 @@
Changelog

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
proxy.

Expand Down
4 changes: 3 additions & 1 deletion RELEASE-NOTES
Expand Up @@ -13,6 +13,7 @@ This release includes the following changes:

o added CURLOPT_NEW_FILE_PERMS and CURLOPT_NEW_DIRECTORY_PERMS
o improved hashing of sockets for the multi_socket API
o ftp kerberos5 support added

This release includes the following bugfixes:

Expand All @@ -36,6 +37,7 @@ New curl mirrors:
This release would not have looked like this without help, code, reports and
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)
2 changes: 1 addition & 1 deletion docs/FEATURES
Expand Up @@ -73,7 +73,7 @@ HTTPS (*1)
FTP
- download
- authentication
- kerberos4 (*5)
- kerberos4 (*5), kerberos5 (*3)
- active/passive using PORT, EPRT, PASV or EPSV
- single file size information (compare to HTTP HEAD)
- 'type=' URL support
Expand Down
15 changes: 8 additions & 7 deletions docs/MANUAL
Expand Up @@ -809,18 +809,19 @@ CUSTOM OUTPUT

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
installed and used at curl build time for it to be used.
Curl supports kerberos4 and kerberos5/GSSAPI for FTP transfers. You need
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
curl in way similar to:
First, get the krb-ticket the normal way, like with the kinit/kauth tool.
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
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

Expand Down
11 changes: 6 additions & 5 deletions docs/curl.1
Expand Up @@ -593,13 +593,14 @@ private key is. DER, PEM and ENG are supported. If not specified, PEM is
assumed.

If this option is used several times, the last one will be used.
.IP "--krb4 <level>"
(FTP) Enable Kerberos4 authentication and use. The level must be entered and
.IP "--krb <level>"
(FTP) Enable Kerberos authentication and use. The level must be entered and
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.

This option requires that the library was built with Kerberos4 support. This
is not very common. Use \fI-V/--version\fP to see if your curl supports it.
This option requires that the library was built with kerberos4 or GSSAPI
(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.
.IP "-K/--config <config file>"
Expand Down Expand Up @@ -1153,7 +1154,7 @@ Automatic decompression of compressed files over HTTP is supported.
.IP "NTLM"
NTLM authentication is supported.
.IP "GSS-Negotiate"
Negotiate authentication is supported.
Negotiate authentication and krb5 for ftp is supported.
.IP "Debug"
This curl uses a libcurl built with Debug. This enables more error-tracking
and memory debugging etc. For curl-developers only!
Expand Down
12 changes: 6 additions & 6 deletions docs/libcurl/curl_easy_setopt.3
Expand Up @@ -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
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)
.IP CURLOPT_KRB4LEVEL
Pass a char * as parameter. Set the krb4 security level, this also enables
krb4 awareness. This is a string, 'clear', 'safe', 'confidential' or
\&'private'. If the string is set but doesn't match one of these, 'private'
will be used. Set the string to NULL to disable Kerberos4. The Kerberos
support only works for FTP.
.IP CURLOPT_KRBLEVEL
Pass a char * as parameter. Set the kerberos security level for FTP; this
also enables kerberos awareness. This is a string, 'clear', 'safe',
'confidential' or \&'private'. If the string is set but doesn't match one
of these, 'private' will be used. Set the string to NULL to disable kerberos
support for FTP.
.SH SSH OPTIONS
.IP CURLOPT_SSH_AUTH_TYPES
Pass a long set to a bitmask consisting of one or more of
Expand Down
10 changes: 6 additions & 4 deletions include/curl/curl.h
Expand Up @@ -736,10 +736,12 @@ typedef enum {
/* Set the interface string to use as outgoing network interface */
CINIT(INTERFACE, OBJECTPOINT, 62),

/* Set the krb4 security level, this also enables krb4 awareness. This is a
* string, 'clear', 'safe', 'confidential' or 'private'. If the string is
* set but doesn't match one of these, 'private' will be used. */
CINIT(KRB4LEVEL, OBJECTPOINT, 63),
/* Set the krb4/5 security level, this also enables krb4/5 awareness. This
* is a string, 'clear', 'safe', 'confidential' or 'private'. If the string
* is set but doesn't match one of these, 'private' will be used. */
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. */
CINIT(SSL_VERIFYPEER, LONG, 64),
Expand Down
1 change: 1 addition & 0 deletions lib/Makefile.inc
Expand Up @@ -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 \
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 \
krb5.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 \
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
Expand Down
97 changes: 68 additions & 29 deletions lib/ftp.c
Expand Up @@ -75,7 +75,7 @@
#include "socks.h"
#include "ftp.h"

#ifdef HAVE_KRB4
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#include "krb4.h"
#endif

Expand Down Expand Up @@ -319,8 +319,17 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
ftpc->cache_size = 0; /* zero the size just in case */
}
else {
int res = Curl_read(conn, sockfd, ptr, BUFSIZE-ftpc->nread_resp,
&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-ftpc->nread_resp,
&gotbytes);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = prot;
#endif
if(res < 0)
/* EWOULDBLOCK */
return CURLE_OK; /* return */
Expand Down Expand Up @@ -360,6 +369,9 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
the line isn't really terminated until the LF comes */

/* output debug output if that is requested */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
if(!conn->sec_complete)
#endif
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
ftpc->linestart_resp, (size_t)perline, conn);
Expand Down Expand Up @@ -414,18 +426,18 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
if(!result)
code = atoi(buf);

#ifdef HAVE_KRB4
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
/* handle the security-oriented responses 6xx ***/
/* FIXME: some errorchecking perhaps... ***/
switch(code) {
case 631:
Curl_sec_read_msg(conn, buf, prot_safe);
code = Curl_sec_read_msg(conn, buf, prot_safe);
break;
case 632:
Curl_sec_read_msg(conn, buf, prot_private);
code = Curl_sec_read_msg(conn, buf, prot_private);
break;
case 633:
Curl_sec_read_msg(conn, buf, prot_confidential);
code = Curl_sec_read_msg(conn, buf, prot_confidential);
break;
default:
/* normal ftp stuff we pass through! */
Expand Down Expand Up @@ -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 */
}
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)
/* EWOULDBLOCK */
continue; /* go looping again */
Expand Down Expand Up @@ -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 */

/* output debug output if that is requested */
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
if(!conn->sec_complete)
#endif
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
line_start, (size_t)perline, conn);
Expand Down Expand Up @@ -646,18 +671,18 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
if(!result)
code = atoi(buf);

#ifdef HAVE_KRB4
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
/* handle the security-oriented responses 6xx ***/
/* FIXME: some errorchecking perhaps... ***/
switch(code) {
case 631:
Curl_sec_read_msg(conn, buf, prot_safe);
code = Curl_sec_read_msg(conn, buf, prot_safe);
break;
case 632:
Curl_sec_read_msg(conn, buf, prot_private);
code = Curl_sec_read_msg(conn, buf, prot_private);
break;
case 633:
Curl_sec_read_msg(conn, buf, prot_confidential);
code = Curl_sec_read_msg(conn, buf, prot_confidential);
break;
default:
/* normal ftp stuff we pass through! */
Expand Down Expand Up @@ -2299,14 +2324,7 @@ static CURLcode ftp_state_loggedin(struct connectdata *conn)
CURLcode result = CURLE_OK;

#ifdef HAVE_KRB4
if(conn->data->set.krb4) {
/* We are logged in, asked to use Kerberos. Set the requested
* protection level
*/
if(conn->sec_complete)
/* BLOCKING */
Curl_sec_set_protection_level(conn);

if(conn->data->set.krb) {
/* We may need to issue a KAUTH here to have access to the files
* do it if user supplied a password
*/
Expand Down Expand Up @@ -2353,7 +2371,8 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
struct ftp_conn *ftpc = &conn->proto.ftpc;
(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 ...
(the server requires to send the user's password too) */
NBFTPSENDF(conn, "PASS %s", ftp->passwd?ftp->passwd:"");
Expand Down Expand Up @@ -2461,15 +2480,15 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}

/* We have received a 220 response fine, now we proceed. */
#ifdef HAVE_KRB4
if(data->set.krb4) {
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
if(data->set.krb) {
/* If not anonymous login, try a secure login. Note that this
procedure is still BLOCKING. */

Curl_sec_request_prot(conn, "private");
/* We set private first as default, in case the line below fails to
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)
infof(data, "Logging in with password in cleartext!\n");
Expand Down Expand Up @@ -3086,7 +3105,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn, CURLcode status, bool premature
/* free the dir tree and file parts */
freedirs(conn);

#ifdef HAVE_KRB4
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
Curl_sec_fflush_fd(conn, conn->sock[SECONDARYSOCKET]);
#endif

Expand Down Expand Up @@ -3496,16 +3515,21 @@ CURLcode Curl_nbftpsendf(struct connectdata *conn,
const char *fmt, ...)
{
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;
char *sptr=s;
CURLcode res = CURLE_OK;
struct SessionHandle *data = conn->data;
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_start(ap, fmt);
vsnprintf(s, 250, fmt, ap);
vsnprintf(s, SBUF_SIZE-3, fmt, ap);
va_end(ap);

strcat(s, "\r\n"); /* append a trailing CRLF */
Expand All @@ -3523,8 +3547,14 @@ CURLcode Curl_nbftpsendf(struct connectdata *conn,
}
#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,
&bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = data_sec;
#endif

if(CURLE_OK != res)
return res;
Expand Down Expand Up @@ -3557,14 +3587,17 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
const char *fmt, ...)
{
ssize_t bytes_written;
char s[256];
char s[SBUF_SIZE];
size_t write_len;
char *sptr=s;
CURLcode res = CURLE_OK;
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
enum protection_level data_sec = conn->data_prot;
#endif

va_list ap;
va_start(ap, fmt);
vsnprintf(s, 250, fmt, ap);
vsnprintf(s, SBUF_SIZE-3, fmt, ap);
va_end(ap);

strcat(s, "\r\n"); /* append a trailing CRLF */
Expand All @@ -3581,8 +3614,14 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
#endif /* CURL_DOES_CONVERSIONS */

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,
&bytes_written);
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = data_sec;
#endif

if(CURLE_OK != res)
break;
Expand Down
2 changes: 2 additions & 0 deletions lib/hostip.c
Expand Up @@ -575,6 +575,8 @@ void Curl_freeaddrinfo(Curl_addrinfo *ai)
/* walk over the list and free all entries */
while(ai) {
next = ai->ai_next;
if(ai->ai_canonname)
free(ai->ai_canonname);
free(ai);
ai = next;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/hostip4.c
Expand Up @@ -380,6 +380,9 @@ Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port)
and use that area to store the address */
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 */

addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */
Expand Down

0 comments on commit 54967d2

Please sign in to comment.