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:
Daniel Stenberg 2007-07-01 22:01:18 +00:00
parent 667fd9a60b
commit 54967d2a3a
19 changed files with 509 additions and 92 deletions

View file

@ -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 \

View file

@ -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;

View file

@ -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;
}

View file

@ -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 */

View file

@ -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) {

View file

@ -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
View 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 */

View file

@ -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;
}

View file

@ -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);

View file

@ -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:
/*

View file

@ -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 */