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
|
||||
|
||||
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.
|
||||
|
||||
|
@ -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:
|
||||
|
||||
@ -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)
|
||||
|
@ -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
|
||||
|
15
docs/MANUAL
15
docs/MANUAL
@ -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
|
||||
|
||||
|
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.
|
||||
|
||||
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>"
|
||||
@ -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!
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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 \
|
||||
|
97
lib/ftp.c
97
lib/ftp.c
@ -75,7 +75,7 @@
|
||||
#include "socks.h"
|
||||
#include "ftp.h"
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#include "krb4.h"
|
||||
#endif
|
||||
|
||||
@ -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 */
|
||||
@ -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);
|
||||
@ -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! */
|
||||
@ -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 */
|
||||
@ -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);
|
||||
@ -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! */
|
||||
@ -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
|
||||
*/
|
||||
@ -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:"");
|
||||
@ -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");
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
@ -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;
|
||||
@ -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 */
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -279,9 +279,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
||||
/* the given address is numerical only, prevent a reverse lookup */
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
}
|
||||
#if 0 /* removed nov 8 2005 before 7.15.1 */
|
||||
else
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
#ifdef HAVE_GSSAPI
|
||||
if(conn->data->set.krb)
|
||||
/* if krb is used, we (might) need the canonical host name */
|
||||
hints.ai_flags |= AI_CANONNAME;
|
||||
#endif
|
||||
|
||||
if(port) {
|
||||
|
@ -40,7 +40,12 @@ struct Curl_sec_client_mech {
|
||||
#define AUTH_CONTINUE 1
|
||||
#define AUTH_ERROR 2
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
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);
|
||||
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"
|
||||
|
||||
#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 */
|
||||
#include <curl/mprintf.h>
|
||||
@ -87,8 +87,8 @@ name_to_level(const char *name)
|
||||
}
|
||||
|
||||
static const struct Curl_sec_client_mech * const mechs[] = {
|
||||
#ifdef KRB5
|
||||
/* not supported */
|
||||
#ifdef HAVE_GSSAPI
|
||||
&Curl_krb5_client_mech,
|
||||
#endif
|
||||
#ifdef HAVE_KRB4
|
||||
&Curl_krb4_client_mech,
|
||||
@ -118,6 +118,8 @@ block_read(int fd, void *buf, size_t len)
|
||||
b = read(fd, p, len);
|
||||
if (b == 0)
|
||||
return 0;
|
||||
else if (b < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
continue;
|
||||
else if (b < 0)
|
||||
return -1;
|
||||
len -= b;
|
||||
@ -133,7 +135,9 @@ block_write(int fd, void *buf, size_t len)
|
||||
int b;
|
||||
while(len) {
|
||||
b = write(fd, p, len);
|
||||
if(b < 0)
|
||||
if (b < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
continue;
|
||||
else if(b < 0)
|
||||
return -1;
|
||||
len -= b;
|
||||
p += b;
|
||||
@ -155,7 +159,7 @@ sec_get_data(struct connectdata *conn,
|
||||
return -1;
|
||||
len = ntohl(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)
|
||||
return 0;
|
||||
else if (b < 0)
|
||||
@ -234,11 +238,36 @@ sec_send(struct connectdata *conn, int fd, char *from, int length)
|
||||
{
|
||||
int bytes;
|
||||
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);
|
||||
bytes = htonl(bytes);
|
||||
block_write(fd, &bytes, sizeof(bytes));
|
||||
block_write(fd, buf, ntohl(bytes));
|
||||
if(iscmd) {
|
||||
char *cmdbuf;
|
||||
|
||||
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);
|
||||
return length;
|
||||
}
|
||||
@ -267,6 +296,8 @@ Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length)
|
||||
return write(fd, buffer, length);
|
||||
|
||||
len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len);
|
||||
if(len <= 0)
|
||||
len = length;
|
||||
while(length){
|
||||
if(length < len)
|
||||
len = length;
|
||||
@ -319,6 +350,11 @@ Curl_sec_read_msg(struct connectdata *conn, char *s, int level)
|
||||
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';
|
||||
|
||||
if(buf[3] == '-')
|
||||
@ -360,7 +396,7 @@ sec_prot_internal(struct connectdata *conn, int level)
|
||||
if(Curl_GetFTPResponse(&nread, conn, &code))
|
||||
return -1;
|
||||
|
||||
if(code/100 != '2'){
|
||||
if(code/100 != 2){
|
||||
failf(conn->data, "Failed to set protection buffer size.");
|
||||
return -1;
|
||||
}
|
||||
@ -385,6 +421,8 @@ sec_prot_internal(struct connectdata *conn, int level)
|
||||
}
|
||||
|
||||
conn->data_prot = (enum protection_level)level;
|
||||
if(level == prot_private)
|
||||
conn->command_prot = (enum protection_level)level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -468,6 +506,9 @@ Curl_sec_login(struct connectdata *conn)
|
||||
conn->mech = *m;
|
||||
conn->sec_complete = 1;
|
||||
conn->command_prot = prot_safe;
|
||||
/* Set the requested protection level */
|
||||
/* BLOCKING */
|
||||
Curl_sec_set_protection_level(conn);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
||||
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
#include "krb4.h"
|
||||
#else
|
||||
#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);
|
||||
#endif /* !USE_LIBSSH2 */
|
||||
else if(conn->sec_complete)
|
||||
/* only TRUE if krb4 enabled */
|
||||
/* only TRUE if krb enabled */
|
||||
bytes_written = Curl_sec_send(conn, num, mem, len);
|
||||
else
|
||||
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 */
|
||||
#include <curl/mprintf.h>
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
#include "krb4.h"
|
||||
#endif
|
||||
#include "memory.h"
|
||||
|
||||
/* 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);
|
||||
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.krb4 = (bool)(NULL != data->set.krb4_level);
|
||||
data->set.krb_level = va_arg(param, char *);
|
||||
data->set.krb = (bool)(NULL != data->set.krb_level);
|
||||
break;
|
||||
case CURLOPT_SSL_VERIFYPEER:
|
||||
/*
|
||||
|
@ -133,8 +133,8 @@
|
||||
We prefix with CURL to prevent name collisions. */
|
||||
#define CURLMAX(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
#ifdef HAVE_KRB4
|
||||
/* Types needed for krb4-ftp connections */
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
/* Types needed for krb4/5-ftp connections */
|
||||
struct krb4buffer {
|
||||
void *data;
|
||||
size_t size;
|
||||
@ -145,7 +145,8 @@ enum protection_level {
|
||||
prot_clear,
|
||||
prot_safe,
|
||||
prot_confidential,
|
||||
prot_private
|
||||
prot_private,
|
||||
prot_cmd
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -882,8 +883,8 @@ struct connectdata {
|
||||
char *cookiehost; /* free later if not NULL */
|
||||
} allocptr;
|
||||
|
||||
int sec_complete; /* if krb4 is enabled for this connection */
|
||||
#ifdef HAVE_KRB4
|
||||
int sec_complete; /* if kerberos is enabled for this connection */
|
||||
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
|
||||
enum protection_level command_prot;
|
||||
enum protection_level 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
|
||||
* 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 */
|
||||
|
||||
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
|
||||
$HOME/.netrc */
|
||||
bool verbose;
|
||||
bool krb4; /* kerberos4 connection requested */
|
||||
bool krb; /* kerberos connection requested */
|
||||
bool reuse_forbid; /* forbidden to be reused, close after use */
|
||||
bool reuse_fresh; /* do not re-use an existing connection */
|
||||
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 crlf;
|
||||
char *customrequest;
|
||||
char *krb4level;
|
||||
char *krblevel;
|
||||
char *trace_dump; /* file to dump the network trace to, or NULL */
|
||||
FILE *trace_stream;
|
||||
bool trace_fopened;
|
||||
@ -665,7 +665,7 @@ static void help(void)
|
||||
" -I/--head Show document info only",
|
||||
" -j/--junk-session-cookies Ignore session cookies read from file (H)",
|
||||
" --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/--config Specify which config file to read",
|
||||
" --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},
|
||||
{"*v", "stderr", TRUE},
|
||||
{"*w", "interface", TRUE},
|
||||
{"*x", "krb4", TRUE},
|
||||
{"*x", "krb" , TRUE},
|
||||
{"*x", "krb4" , TRUE}, /* this is the previous name */
|
||||
{"*y", "max-filesize", TRUE},
|
||||
{"*z", "disable-eprt", FALSE},
|
||||
{"$a", "ftp-ssl", FALSE},
|
||||
@ -1809,10 +1810,10 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
||||
/* interface */
|
||||
GetStr(&config->iface, nextarg);
|
||||
break;
|
||||
case 'x': /* --krb4 */
|
||||
/* krb4 level string */
|
||||
if(curlinfo->features & CURL_VERSION_KERBEROS4)
|
||||
GetStr(&config->krb4level, nextarg);
|
||||
case 'x': /* --krb */
|
||||
/* kerberos level string */
|
||||
if(curlinfo->features & (CURL_VERSION_KERBEROS4 | CURL_VERSION_GSSNEGOTIATE))
|
||||
GetStr(&config->krblevel, nextarg);
|
||||
else
|
||||
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
||||
break;
|
||||
@ -3260,8 +3261,8 @@ static void free_config_fields(struct Configurable *config)
|
||||
free(config->cookie);
|
||||
if(config->cookiefile)
|
||||
free(config->cookiefile);
|
||||
if(config->krb4level)
|
||||
free(config->krb4level);
|
||||
if(config->krblevel)
|
||||
free(config->krblevel);
|
||||
if(config->headerfile)
|
||||
free(config->headerfile);
|
||||
if(config->ftpport)
|
||||
@ -4221,7 +4222,7 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
|
||||
/* three new ones in libcurl 7.3: */
|
||||
my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
|
||||
my_setopt(curl, CURLOPT_INTERFACE, config->iface);
|
||||
my_setopt(curl, CURLOPT_KRB4LEVEL, config->krb4level);
|
||||
my_setopt(curl, CURLOPT_KRBLEVEL, config->krblevel);
|
||||
|
||||
progressbarinit(&progressbar, config);
|
||||
if((config->progressmode == CURL_PROGRESS_BAR) &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user