diff options
author | Curl Upstream <curl-library@cool.haxx.se> | 2014-09-10 06:07:58 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2014-10-08 19:53:25 (GMT) |
commit | 3fe5d9bff98b4716e219516c30d71462495324f4 (patch) | |
tree | cd369c3f671882cefde2f68a1ac8146f97c6bc84 /lib/security.c | |
parent | f086cb372e41035260fcd9b4ed3d2cfb272f138f (diff) | |
download | CMake-3fe5d9bff98b4716e219516c30d71462495324f4.zip CMake-3fe5d9bff98b4716e219516c30d71462495324f4.tar.gz CMake-3fe5d9bff98b4716e219516c30d71462495324f4.tar.bz2 |
curl 7.38.0 (reduced)
Extract upstream curl using the following shell code.
url=git://github.com/bagder/curl.git &&
v=7.38.0 &&
r=202aa9f7 &&
paths="
CMake/*
CMakeLists.txt
COPYING
include/curl/*.h
include/curl/curlbuild.h.cmake
lib/*.c
lib/*.h
lib/CMakeLists.txt
lib/Makefile.inc
lib/curl_config.h.cmake
lib/libcurl.rc
lib/vtls/*.c
lib/vtls/*.h
" &&
mkdir curl-$v-g$r-reduced &&
git clone $url curl-git &&
date=$(cd curl-git && git log -n 1 --format='%cd' $r) &&
(cd curl-git && git checkout $r &&
git archive --format=tar $r -- $paths) |
(cd curl-$v-g$r-reduced && tar xv &&
rm lib/config-*.h) &&
echo "g$r date: $date"
Diffstat (limited to 'lib/security.c')
-rw-r--r-- | lib/security.c | 700 |
1 files changed, 404 insertions, 296 deletions
diff --git a/lib/security.c b/lib/security.c index 4c9aed8..508c7b4 100644 --- a/lib/security.c +++ b/lib/security.c @@ -7,8 +7,11 @@ * rewrite to work around the paragraph 2 in the BSD licenses as explained * below. * - * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan + * Copyright (c) 1998, 1999, 2013 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). + * + * Copyright (C) 2001 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,42 +41,39 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include "setup.h" +#include "curl_setup.h" #ifndef CURL_DISABLE_FTP -#ifdef HAVE_KRB4 +#ifdef HAVE_GSSAPI -#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */ -#include <curl/mprintf.h> - -#include <stdlib.h> -#include <string.h> +#ifdef HAVE_NETDB_H #include <netdb.h> +#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> #endif #include "urldata.h" -#include "krb4.h" -#include "base64.h" -#include "sendf.h" +#include "curl_base64.h" +#include "curl_memory.h" +#include "curl_sec.h" #include "ftp.h" -#include "memory.h" +#include "sendf.h" +#include "rawstr.h" +#include "warnless.h" /* The last #include file should be: */ #include "memdebug.h" -#define min(a, b) ((a) < (b) ? (a) : (b)) - static const struct { - enum protection_level level; - const char *name; + enum protection_level level; + const char *name; } level_names[] = { - { prot_clear, "clear" }, - { prot_safe, "safe" }, - { prot_confidential, "confidential" }, - { prot_private, "private" } + { PROT_CLEAR, "clear" }, + { PROT_SAFE, "safe" }, + { PROT_CONFIDENTIAL, "confidential" }, + { PROT_PRIVATE, "private" } }; static enum protection_level @@ -81,196 +81,270 @@ name_to_level(const char *name) { int i; for(i = 0; i < (int)sizeof(level_names)/(int)sizeof(level_names[0]); i++) - if(curl_strnequal(level_names[i].name, name, strlen(name))) + if(checkprefix(name, level_names[i].name)) return level_names[i].level; - return (enum protection_level)-1; + return PROT_NONE; +} + +/* Convert a protocol |level| to its char representation. + We take an int to catch programming mistakes. */ +static char level_to_char(int level) { + switch(level) { + case PROT_CLEAR: + return 'C'; + case PROT_SAFE: + return 'S'; + case PROT_CONFIDENTIAL: + return 'E'; + case PROT_PRIVATE: + return 'P'; + case PROT_CMD: + /* Fall through */ + default: + /* Those 2 cases should not be reached! */ + break; + } + DEBUGASSERT(0); + /* Default to the most secure alternative. */ + return 'P'; } 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, -#endif - NULL + NULL }; -int -Curl_sec_getc(struct connectdata *conn, FILE *F) +/* Send an FTP command defined by |message| and the optional arguments. The + function returns the ftp_code. If an error occurs, -1 is returned. */ +static int ftp_send_command(struct connectdata *conn, const char *message, ...) { - if(conn->sec_complete && conn->data_prot) { - char c; - if(Curl_sec_read(conn, fileno(F), &c, 1) <= 0) - return EOF; - return c; + int ftp_code; + ssize_t nread; + va_list args; + char print_buffer[50]; + + va_start(args, message); + vsnprintf(print_buffer, sizeof(print_buffer), message, args); + va_end(args); + + if(Curl_ftpsendf(conn, print_buffer) != CURLE_OK) { + ftp_code = -1; } - else - return getc(F); + else { + if(Curl_GetFTPResponse(&nread, conn, &ftp_code) != CURLE_OK) + ftp_code = -1; + } + + (void)nread; /* Unused */ + return ftp_code; } -static int -block_read(int fd, void *buf, size_t len) +/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode + saying whether an error occurred or CURLE_OK if |len| was read. */ +static CURLcode +socket_read(curl_socket_t fd, void *to, size_t len) { - unsigned char *p = buf; - int b; - while(len) { - b = read(fd, p, len); - if (b == 0) - return 0; - else if (b < 0) - return -1; - len -= b; - p += b; + char *to_p = to; + CURLcode code; + ssize_t nread; + + while(len > 0) { + code = Curl_read_plain(fd, to_p, len, &nread); + if(code == CURLE_OK) { + len -= nread; + to_p += nread; + } + else { + /* FIXME: We are doing a busy wait */ + if(code == CURLE_AGAIN) + continue; + return code; + } } - return p - (unsigned char*)buf; + return CURLE_OK; } -static int -block_write(int fd, void *buf, size_t len) + +/* Write |len| bytes from the buffer |to| to the socket |fd|. Return a + CURLcode saying whether an error occurred or CURLE_OK if |len| was + written. */ +static CURLcode +socket_write(struct connectdata *conn, curl_socket_t fd, const void *to, + size_t len) { - unsigned char *p = buf; - int b; - while(len) { - b = write(fd, p, len); - if(b < 0) - return -1; - len -= b; - p += b; + const char *to_p = to; + CURLcode code; + ssize_t written; + + while(len > 0) { + code = Curl_write_plain(conn, fd, to_p, len, &written); + if(code == CURLE_OK) { + len -= written; + to_p += written; + } + else { + /* FIXME: We are doing a busy wait */ + if(code == CURLE_AGAIN) + continue; + return code; + } } - return p - (unsigned char*)buf; + return CURLE_OK; } -static int -sec_get_data(struct connectdata *conn, - int fd, struct krb4buffer *buf) +static CURLcode read_data(struct connectdata *conn, + curl_socket_t fd, + struct krb5buffer *buf) { int len; - int b; + void* tmp; + CURLcode ret; + + ret = socket_read(fd, &len, sizeof(len)); + if(ret != CURLE_OK) + return ret; - b = block_read(fd, &len, sizeof(len)); - if (b == 0) - return 0; - else if (b < 0) - return -1; len = ntohl(len); - buf->data = realloc(buf->data, len); - b = block_read(fd, buf->data, len); - if (b == 0) - return 0; - else if (b < 0) - return -1; - buf->size = (conn->mech->decode)(conn->app_data, buf->data, len, - conn->data_prot, conn); + tmp = realloc(buf->data, len); + if(tmp == NULL) + return CURLE_OUT_OF_MEMORY; + + buf->data = tmp; + ret = socket_read(fd, buf->data, len); + if(ret != CURLE_OK) + return ret; + buf->size = conn->mech->decode(conn->app_data, buf->data, len, + conn->data_prot, conn); buf->index = 0; - return 0; + return CURLE_OK; } static size_t -buffer_read(struct krb4buffer *buf, void *data, size_t len) +buffer_read(struct krb5buffer *buf, void *data, size_t len) { - len = min(len, buf->size - buf->index); - memcpy(data, (char*)buf->data + buf->index, len); - buf->index += len; - return len; + if(buf->size - buf->index < len) + len = buf->size - buf->index; + memcpy(data, (char*)buf->data + buf->index, len); + buf->index += len; + return len; } -static size_t -buffer_write(struct krb4buffer *buf, void *data, size_t len) +/* Matches Curl_recv signature */ +static ssize_t sec_recv(struct connectdata *conn, int sockindex, + char *buffer, size_t len, CURLcode *err) { - if(buf->index + len > buf->size) { - void *tmp; - if(buf->data == NULL) - tmp = malloc(1024); - else - tmp = realloc(buf->data, buf->index + len); - if(tmp == NULL) - return -1; - buf->data = tmp; - buf->size = buf->index + len; - } - memcpy((char*)buf->data + buf->index, data, len); - buf->index += len; - return len; -} + size_t bytes_read; + size_t total_read = 0; + curl_socket_t fd = conn->sock[sockindex]; -int -Curl_sec_read(struct connectdata *conn, int fd, void *buffer, int length) -{ - size_t len; - int rx = 0; + *err = CURLE_OK; - if(conn->sec_complete == 0 || conn->data_prot == 0) - return read(fd, buffer, length); + /* Handle clear text response. */ + if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR) + return read(fd, buffer, len); - if(conn->in_buffer.eof_flag){ - conn->in_buffer.eof_flag = 0; - return 0; - } + if(conn->in_buffer.eof_flag) { + conn->in_buffer.eof_flag = 0; + return 0; + } - len = buffer_read(&conn->in_buffer, buffer, length); - length -= len; - rx += len; - buffer = (char*)buffer + len; - - while(length) { - if(sec_get_data(conn, fd, &conn->in_buffer) < 0) - return -1; - if(conn->in_buffer.size == 0) { - if(rx) - conn->in_buffer.eof_flag = 1; - return rx; - } - len = buffer_read(&conn->in_buffer, buffer, length); - length -= len; - rx += len; - buffer = (char*)buffer + len; - } - return rx; -} + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; -static int -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, - &buf, conn); - bytes = htonl(bytes); - block_write(fd, &bytes, sizeof(bytes)); - block_write(fd, buf, ntohl(bytes)); - free(buf); - return length; + while(len > 0) { + if(read_data(conn, fd, &conn->in_buffer) != CURLE_OK) + return -1; + if(conn->in_buffer.size == 0) { + if(bytes_read > 0) + conn->in_buffer.eof_flag = 1; + return bytes_read; + } + bytes_read = buffer_read(&conn->in_buffer, buffer, len); + len -= bytes_read; + total_read += bytes_read; + buffer += bytes_read; + } + /* FIXME: Check for overflow */ + return total_read; } -int -Curl_sec_fflush_fd(struct connectdata *conn, int fd) +/* Send |length| bytes from |from| to the |fd| socket taking care of encoding + and negociating with the server. |from| can be NULL. */ +/* FIXME: We don't check for errors nor report any! */ +static void do_sec_send(struct connectdata *conn, curl_socket_t fd, + const char *from, int length) { - if(conn->data_prot != prot_clear) { - if(conn->out_buffer.index > 0){ - Curl_sec_write(conn, fd, - conn->out_buffer.data, conn->out_buffer.index); - conn->out_buffer.index = 0; + int bytes, htonl_bytes; /* 32-bit integers for htonl */ + char *buffer = NULL; + char *cmd_buffer; + size_t cmd_size = 0; + CURLcode error; + enum protection_level prot_level = conn->data_prot; + bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE; + + DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST); + + if(iscmd) { + if(!strncmp(from, "PASS ", 5) || !strncmp(from, "ACCT ", 5)) + prot_level = PROT_PRIVATE; + else + prot_level = conn->command_prot; + } + bytes = conn->mech->encode(conn->app_data, from, length, prot_level, + (void**)&buffer, conn); + if(!buffer || bytes <= 0) + return; /* error */ + + if(iscmd) { + error = Curl_base64_encode(conn->data, buffer, curlx_sitouz(bytes), + &cmd_buffer, &cmd_size); + if(error) { + free(buffer); + return; /* error */ + } + if(cmd_size > 0) { + static const char *enc = "ENC "; + static const char *mic = "MIC "; + if(prot_level == PROT_PRIVATE) + socket_write(conn, fd, enc, 4); + else + socket_write(conn, fd, mic, 4); + + socket_write(conn, fd, cmd_buffer, cmd_size); + socket_write(conn, fd, "\r\n", 2); + infof(conn->data, "Send: %s%s\n", prot_level == PROT_PRIVATE?enc:mic, + cmd_buffer); + free(cmd_buffer); } - sec_send(conn, fd, NULL, 0); } - return 0; + else { + htonl_bytes = htonl(bytes); + socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes)); + socket_write(conn, fd, buffer, curlx_sitouz(bytes)); + } + free(buffer); } -int -Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length) +static ssize_t sec_write(struct connectdata *conn, curl_socket_t fd, + const char *buffer, size_t length) { - int len = conn->buffer_size; - int tx = 0; - - if(conn->data_prot == prot_clear) - return write(fd, buffer, length); - - len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len); - while(length){ - if(length < len) + /* FIXME: Check for overflow */ + ssize_t tx = 0, len = conn->buffer_size; + + len -= conn->mech->overhead(conn->app_data, conn->data_prot, + curlx_sztosi(len)); + if(len <= 0) + len = length; + while(length) { + if(len >= 0 || length < (size_t)len) { + /* FIXME: Check for overflow. */ len = length; - sec_send(conn, fd, buffer, len); + } + do_sec_send(conn, fd, buffer, curlx_sztosi(len)); length -= len; buffer += len; tx += len; @@ -278,216 +352,250 @@ Curl_sec_write(struct connectdata *conn, int fd, char *buffer, int length) return tx; } -ssize_t -Curl_sec_send(struct connectdata *conn, int num, char *buffer, int length) -{ - curl_socket_t fd = conn->sock[num]; - return (ssize_t)Curl_sec_write(conn, fd, buffer, length); -} - -int -Curl_sec_putc(struct connectdata *conn, int c, FILE *F) +/* Matches Curl_send signature */ +static ssize_t sec_send(struct connectdata *conn, int sockindex, + const void *buffer, size_t len, CURLcode *err) { - char ch = c; - if(conn->data_prot == prot_clear) - return putc(c, F); - - buffer_write(&conn->out_buffer, &ch, 1); - if(c == '\n' || conn->out_buffer.index >= 1024 /* XXX */) { - Curl_sec_write(conn, fileno(F), conn->out_buffer.data, - conn->out_buffer.index); - conn->out_buffer.index = 0; - } - return c; + curl_socket_t fd = conn->sock[sockindex]; + *err = CURLE_OK; + return sec_write(conn, fd, buffer, len); } -int -Curl_sec_read_msg(struct connectdata *conn, char *s, int level) +int Curl_sec_read_msg(struct connectdata *conn, char *buffer, + enum protection_level level) { - int len; - unsigned char *buf; - int code; + /* decoded_len should be size_t or ssize_t but conn->mech->decode returns an + int */ + int decoded_len; + char *buf; + int ret_code; + size_t decoded_sz = 0; + CURLcode error; + + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); + + error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz); + if(error || decoded_sz == 0) + return -1; - len = Curl_base64_decode(s + 4, &buf); /* XXX */ - if(len > 0) - len = (conn->mech->decode)(conn->app_data, buf, len, level, conn); - else + if(decoded_sz > (size_t)INT_MAX) { + free(buf); return -1; + } + decoded_len = curlx_uztosi(decoded_sz); - if(len < 0) { + decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len, + level, conn); + if(decoded_len <= 0) { free(buf); return -1; } - buf[len] = '\0'; + if(conn->data->set.verbose) { + buf[decoded_len] = '\n'; + Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn); + } + buf[decoded_len] = '\0'; + DEBUGASSERT(decoded_len > 3); if(buf[3] == '-') - code = 0; - else - sscanf((char *)buf, "%d", &code); - if(buf[len-1] == '\n') - buf[len-1] = '\0'; - strcpy(s, (char *)buf); + ret_code = 0; + else { + /* Check for error? */ + sscanf(buf, "%d", &ret_code); + } + + if(buf[decoded_len - 1] == '\n') + buf[decoded_len - 1] = '\0'; + /* FIXME: Is |buffer| length always greater than |decoded_len|? */ + strcpy(buffer, buf); free(buf); - return code; + return ret_code; } -enum protection_level -Curl_set_command_prot(struct connectdata *conn, enum protection_level level) +/* FIXME: The error code returned here is never checked. */ +static int sec_set_protection_level(struct connectdata *conn) { - enum protection_level old = conn->command_prot; - conn->command_prot = level; - return old; -} + int code; + char* pbsz; + static unsigned int buffer_size = 1 << 20; /* 1048576 */ + enum protection_level level = conn->request_data_prot; -static int -sec_prot_internal(struct connectdata *conn, int level) -{ - char *p; - unsigned int s = 1048576; - ssize_t nread; + DEBUGASSERT(level > PROT_NONE && level < PROT_LAST); - if(!conn->sec_complete){ - infof(conn->data, "No security data exchange has taken place.\n"); + if(!conn->sec_complete) { + infof(conn->data, "Trying to change the protection level after the" + "completion of the data exchange.\n"); return -1; } - if(level){ - int code; - if(Curl_ftpsendf(conn, "PBSZ %u", s)) - return -1; + /* Bail out if we try to set up the same level */ + if(conn->data_prot == level) + return 0; - if(Curl_GetFTPResponse(&nread, conn, &code)) + if(level) { + code = ftp_send_command(conn, "PBSZ %u", buffer_size); + if(code < 0) return -1; - if(code/100 != '2'){ - failf(conn->data, "Failed to set protection buffer size."); + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection's buffer size."); return -1; } - conn->buffer_size = s; - - p = strstr(conn->data->state.buffer, "PBSZ="); - if(p) - sscanf(p, "PBSZ=%u", &s); - if(s < conn->buffer_size) - conn->buffer_size = s; + conn->buffer_size = buffer_size; + + pbsz = strstr(conn->data->state.buffer, "PBSZ="); + if(pbsz) { + /* FIXME: Checks for errors in sscanf? */ + sscanf(pbsz, "PBSZ=%u", &buffer_size); + if(buffer_size < conn->buffer_size) + conn->buffer_size = buffer_size; + } } - if(Curl_ftpsendf(conn, "PROT %c", level["CSEP"])) - return -1; + /* Now try to negiociate the protection level. */ + code = ftp_send_command(conn, "PROT %c", level_to_char(level)); - if(Curl_GetFTPResponse(&nread, conn, NULL)) + if(code < 0) return -1; - if(conn->data->state.buffer[0] != '2'){ - failf(conn->data, "Failed to set protection level."); + if(code/100 != 2) { + failf(conn->data, "Failed to set the protection level."); return -1; } - conn->data_prot = (enum protection_level)level; - return 0; -} + conn->data_prot = level; + if(level == PROT_PRIVATE) + conn->command_prot = level; -void -Curl_sec_set_protection_level(struct connectdata *conn) -{ - if(conn->sec_complete && conn->data_prot != conn->request_data_prot) - sec_prot_internal(conn, conn->request_data_prot); + return 0; } - int Curl_sec_request_prot(struct connectdata *conn, const char *level) { - int l = name_to_level(level); - if(l == -1) + enum protection_level l = name_to_level(level); + if(l == PROT_NONE) return -1; - conn->request_data_prot = (enum protection_level)l; + DEBUGASSERT(l > PROT_NONE && l < PROT_LAST); + conn->request_data_prot = l; return 0; } -int -Curl_sec_login(struct connectdata *conn) +static CURLcode choose_mech(struct connectdata *conn) { int ret; - const struct Curl_sec_client_mech * const *m; - ssize_t nread; - struct SessionHandle *data=conn->data; - int ftpcode; - - for(m = mechs; *m && (*m)->name; m++) { - void *tmp; - - tmp = realloc(conn->app_data, (*m)->size); - if (tmp == NULL) { - failf (data, "realloc %u failed", (*m)->size); - return -1; - } - conn->app_data = tmp; - - if((*m)->init && (*(*m)->init)(conn->app_data) != 0) { - infof(data, "Skipping %s...\n", (*m)->name); + struct SessionHandle *data = conn->data; + const struct Curl_sec_client_mech * const *mech; + void *tmp_allocation; + const char *mech_name; + + for(mech = mechs; (*mech); ++mech) { + mech_name = (*mech)->name; + /* We have no mechanism with a NULL name but keep this check */ + DEBUGASSERT(mech_name != NULL); + if(mech_name == NULL) { + infof(data, "Skipping mechanism with empty name (%p)\n", (void *)mech); continue; } - infof(data, "Trying %s...\n", (*m)->name); + tmp_allocation = realloc(conn->app_data, (*mech)->size); + if(tmp_allocation == NULL) { + failf(data, "Failed realloc of size %u", (*mech)->size); + mech = NULL; + return CURLE_OUT_OF_MEMORY; + } + conn->app_data = tmp_allocation; - if(Curl_ftpsendf(conn, "AUTH %s", (*m)->name)) - return -1; + if((*mech)->init) { + ret = (*mech)->init(conn->app_data); + if(ret != 0) { + infof(data, "Failed initialization for %s. Skipping it.\n", mech_name); + continue; + } + } - if(Curl_GetFTPResponse(&nread, conn, &ftpcode)) - return -1; + infof(data, "Trying mechanism %s...\n", mech_name); + ret = ftp_send_command(conn, "AUTH %s", mech_name); + if(ret < 0) + /* FIXME: This error is too generic but it is OK for now. */ + return CURLE_COULDNT_CONNECT; - if(conn->data->state.buffer[0] != '3'){ - switch(ftpcode) { + if(ret/100 != 3) { + switch(ret) { case 504: - infof(data, - "%s is not supported by the server.\n", (*m)->name); + infof(data, "Mechanism %s is not supported by the server (server " + "returned ftp code: 504).\n", mech_name); break; case 534: - infof(data, "%s rejected as security mechanism.\n", (*m)->name); + infof(data, "Mechanism %s was rejected by the server (server returned " + "ftp code: 534).\n", mech_name); break; default: - if(conn->data->state.buffer[0] == '5') { - infof(data, "The server doesn't support the FTP " - "security extensions.\n"); - return -1; + if(ret/100 == 5) { + infof(data, "server does not support the security extensions\n"); + return CURLE_USE_SSL_FAILED; } break; } continue; } - ret = (*(*m)->auth)(conn->app_data, conn); + /* Authenticate */ + ret = (*mech)->auth(conn->app_data, conn); if(ret == AUTH_CONTINUE) continue; - else if(ret != AUTH_OK){ - /* mechanism is supposed to output error string */ + else if(ret != AUTH_OK) { + /* Mechanism has dumped the error to stderr, don't error here. */ return -1; } - conn->mech = *m; + DEBUGASSERT(ret == AUTH_OK); + + conn->mech = *mech; conn->sec_complete = 1; - conn->command_prot = prot_safe; + conn->recv[FIRSTSOCKET] = sec_recv; + conn->send[FIRSTSOCKET] = sec_send; + conn->recv[SECONDARYSOCKET] = sec_recv; + conn->send[SECONDARYSOCKET] = sec_send; + conn->command_prot = PROT_SAFE; + /* Set the requested protection level */ + /* BLOCKING */ + (void)sec_set_protection_level(conn); break; } - return *m == NULL; + return mech != NULL ? CURLE_OK : CURLE_FAILED_INIT; } +CURLcode +Curl_sec_login(struct connectdata *conn) +{ + return choose_mech(conn); +} + + void Curl_sec_end(struct connectdata *conn) { - if (conn->mech != NULL) { - if(conn->mech->end) - (conn->mech->end)(conn->app_data); - memset(conn->app_data, 0, conn->mech->size); + if(conn->mech != NULL && conn->mech->end) + conn->mech->end(conn->app_data); + if(conn->app_data) { free(conn->app_data); conn->app_data = NULL; } + if(conn->in_buffer.data) { + free(conn->in_buffer.data); + conn->in_buffer.data = NULL; + conn->in_buffer.size = 0; + conn->in_buffer.index = 0; + /* FIXME: Is this really needed? */ + conn->in_buffer.eof_flag = 0; + } conn->sec_complete = 0; - conn->data_prot = (enum protection_level)0; - conn->mech=NULL; + conn->data_prot = PROT_CLEAR; + conn->mech = NULL; } -#endif /* HAVE_KRB4 */ +#endif /* HAVE_GSSAPI */ + #endif /* CURL_DISABLE_FTP */ |