1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-21 23:58:49 -05:00

base64: fix Curl_base64_encode and Curl_base64_decode interfaces

Previous interfaces for these libcurl internal functions did not allow to tell
apart a legitimate zero size result from an error condition. These functions
now return a CURLcode indicating function success or otherwise specific error.
Output size is returned using a pointer argument.

All usage of these two functions, and others closely related, has been adapted
to the new interfaces. Relative error and OOM handling adapted or added where
missing. Unit test 1302 also adapted.
This commit is contained in:
Yang Tse 2011-08-24 08:07:36 +02:00
parent cce6508242
commit fd00b382b2
18 changed files with 380 additions and 225 deletions

View File

@ -68,12 +68,19 @@ static void decodeQuantum(unsigned char *dest, const char *src)
/*
* Curl_base64_decode()
*
* Given a base64 string at src, decode it and return an allocated memory in
* the *outptr. Returns the length of the decoded data.
* Given a base64 NUL-terminated string at src, decode it and return a
* pointer in *outptr to a newly allocated memory area holding decoded
* data. Size of decoded data is returned in variable pointed by outlen.
*
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
* When decoded data length is 0, returns NULL in *outptr.
*
* @unittest: 1302
*/
size_t Curl_base64_decode(const char *src, unsigned char **outptr)
CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen)
{
size_t length = 0;
size_t equalsTerm = 0;
@ -84,6 +91,7 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
unsigned char *newstr;
*outptr = NULL;
*outlen = 0;
while((src[length] != '=') && src[length])
length++;
@ -97,7 +105,7 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
/* Don't allocate a buffer if the decoded length is 0 */
if(numQuantums == 0)
return 0;
return CURLE_OK;
rawlen = (numQuantums * 3) - equalsTerm;
@ -105,7 +113,7 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
(which may be partially thrown out) and the zero terminator. */
newstr = malloc(rawlen+4);
if(!newstr)
return 0;
return CURLE_OUT_OF_MEMORY;
*outptr = newstr;
@ -124,23 +132,34 @@ size_t Curl_base64_decode(const char *src, unsigned char **outptr)
newstr[i] = lastQuantum[i];
newstr[i] = '\0'; /* zero terminate */
return rawlen;
*outlen = rawlen; /* return size of decoded data */
return CURLE_OK;
}
/*
* Curl_base64_encode()
*
* Returns the length of the newly created base64 string. The third argument
* is a pointer to an allocated area holding the base64 data. If something
* went wrong, 0 is returned.
* Given a pointer to an input buffer and an input size, encode it and
* return a pointer in *outptr to a newly allocated memory area holding
* encoded data. Size of encoded data is returned in variable pointed by
* outlen.
*
* Input length of 0 indicates input buffer holds a NUL-terminated string.
*
* Returns CURLE_OK on success, otherwise specific error code. Function
* output shall not be considered valid unless CURLE_OK is returned.
*
* When encoded data length is 0, returns NULL in *outptr.
*
* @unittest: 1302
*/
size_t Curl_base64_encode(struct SessionHandle *data,
CURLcode Curl_base64_encode(struct SessionHandle *data,
const char *inputbuff, size_t insize,
char **outptr)
char **outptr, size_t *outlen)
{
CURLcode res;
CURLcode error;
unsigned char ibuf[3];
unsigned char obuf[4];
int i;
@ -151,24 +170,25 @@ size_t Curl_base64_encode(struct SessionHandle *data,
const char *indata = inputbuff;
*outptr = NULL; /* set to NULL in case of failure before we reach the end */
*outptr = NULL;
*outlen = 0;
if(0 == insize)
insize = strlen(indata);
base64data = output = malloc(insize*4/3+4);
if(NULL == output)
return 0;
return CURLE_OUT_OF_MEMORY;
/*
* The base64 data needs to be created using the network encoding
* not the host encoding. And we can't change the actual input
* so we copy it to a buffer, translate it, and use that instead.
*/
res = Curl_convert_clone(data, indata, insize, &convbuf);
if(res) {
error = Curl_convert_clone(data, indata, insize, &convbuf);
if(error) {
free(output);
return 0;
return error;
}
if(convbuf)
@ -215,12 +235,14 @@ size_t Curl_base64_encode(struct SessionHandle *data,
}
output += 4;
}
*output=0;
*outptr = base64data; /* make it return the actual data memory */
*output = '\0';
*outptr = base64data; /* return pointer to new data, allocated memory */
if(convbuf)
free(convbuf);
return strlen(base64data); /* return the length of the new data */
*outlen = strlen(base64data); /* return the length of the new data */
return CURLE_OK;
}
/* ---- End of Base64 Encoding ---- */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -22,10 +22,11 @@
*
***************************************************************************/
size_t Curl_base64_encode(struct SessionHandle *data,
CURLcode Curl_base64_encode(struct SessionHandle *data,
const char *inputbuff, size_t insize,
char **outptr);
char **outptr, size_t *outlen);
size_t Curl_base64_decode(const char *src, unsigned char **outptr);
CURLcode Curl_base64_decode(const char *src,
unsigned char **outptr, size_t *outlen);
#endif /* HEADER_CURL_BASE64_H */

View File

@ -305,16 +305,22 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data,
(*) -> Optional
*/
size_t size;
unsigned char *buffer;
size_t size = 0;
unsigned char *buffer = NULL;
CURLcode error;
#if defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_WINDOWS_SSPI)
(void)data;
#endif
size = Curl_base64_decode(header, &buffer);
if(!buffer)
return CURLE_OUT_OF_MEMORY;
error = Curl_base64_decode(header, &buffer, &size);
if(error)
return error;
if(!buffer) {
infof(data, "NTLM handshake failure (unhandled condition)\n");
return CURLE_REMOTE_ACCESS_DENIED;
}
#ifdef USE_WINDOWS_SSPI
ntlm->type_2 = malloc(size + 1);

View File

@ -231,11 +231,13 @@ static char *copy_header_value(const char *h)
*/
static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
{
char *authorization;
size_t size = 0;
char *authorization = NULL;
struct SessionHandle *data = conn->data;
char **userp;
const char *user;
const char *pwd;
CURLcode error;
if(proxy) {
userp = &conn->allocptr.proxyuserpwd;
@ -249,20 +251,24 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
}
snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
if(Curl_base64_encode(data, data->state.buffer,
strlen(data->state.buffer),
&authorization) > 0) {
if(*userp)
free(*userp);
error = Curl_base64_encode(data,
data->state.buffer, strlen(data->state.buffer),
&authorization, &size);
if(error)
return error;
if(!authorization)
return CURLE_REMOTE_ACCESS_DENIED;
Curl_safefree(*userp);
*userp = aprintf("%sAuthorization: Basic %s\r\n",
proxy?"Proxy-":"",
authorization);
free(authorization);
if(!*userp)
return CURLE_OUT_OF_MEMORY;
}
else
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}

View File

@ -280,7 +280,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
unsigned char *ha1;
unsigned char ha2[33];/* 32 digits and 1 zero byte */
char cnoncebuf[7];
char *cnonce;
char *cnonce = NULL;
size_t cnonce_sz = 0;
char *tmp = NULL;
struct timeval now;
@ -343,10 +344,12 @@ CURLcode Curl_output_digest(struct connectdata *conn,
/* Generate a cnonce */
now = Curl_tvnow();
snprintf(cnoncebuf, sizeof(cnoncebuf), "%06ld", (long)now.tv_sec);
if(Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), &cnonce))
rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
&cnonce, &cnonce_sz);
if(rc)
return rc;
d->cnonce = cnonce;
else
return CURLE_OUT_OF_MEMORY;
}
/*

View File

@ -138,9 +138,11 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
int ret;
size_t len, rawlen;
size_t len;
size_t rawlen = 0;
bool gss;
const char* protocol;
CURLcode error;
while(*header && ISSPACE(*header))
header++;
@ -183,9 +185,9 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
len = strlen(header);
if(len > 0) {
rawlen = Curl_base64_decode(header,
(unsigned char **)&input_token.value);
if(rawlen == 0)
error = Curl_base64_decode(header,
(unsigned char **)&input_token.value, &rawlen);
if(error || rawlen == 0)
return -1;
input_token.length = rawlen;
@ -270,8 +272,9 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
&conn->data->state.negotiate;
char *encoded = NULL;
size_t len;
size_t len = 0;
char *userp;
CURLcode error;
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
if(checkprefix("Negotiate", neg_ctx->protocol)) {
@ -317,13 +320,21 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
}
}
#endif
len = Curl_base64_encode(conn->data,
error = Curl_base64_encode(conn->data,
neg_ctx->output_token.value,
neg_ctx->output_token.length,
&encoded);
&encoded, &len);
if(error) {
Curl_safefree(neg_ctx->output_token.value);
neg_ctx->output_token.value = NULL;
return error;
}
if(len == 0)
return CURLE_OUT_OF_MEMORY;
if(len == 0) {
Curl_safefree(neg_ctx->output_token.value);
neg_ctx->output_token.value = NULL;
return CURLE_REMOTE_ACCESS_DENIED;
}
userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "",
neg_ctx->protocol, encoded);

View File

@ -94,6 +94,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
size_t len = 0, input_token_len = 0;
bool gss = FALSE;
const char* protocol;
CURLcode error;
while(*header && ISSPACE(*header))
header++;
@ -176,9 +177,10 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
if(!input_token)
return -1;
input_token_len = Curl_base64_decode(header,
(unsigned char **)&input_token);
if(input_token_len == 0)
error = Curl_base64_decode(header,
(unsigned char **)&input_token,
&input_token_len);
if(error || input_token_len == 0)
return -1;
}
@ -238,16 +240,19 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
&conn->data->state.negotiate;
char *encoded = NULL;
size_t len;
size_t len = 0;
char *userp;
CURLcode error;
len = Curl_base64_encode(conn->data,
error = Curl_base64_encode(conn->data,
(const char*)neg_ctx->output_token,
neg_ctx->output_token_length,
&encoded);
&encoded, &len);
if(error)
return error;
if(len == 0)
return CURLE_OUT_OF_MEMORY;
return CURLE_REMOTE_ACCESS_DENIED;
userp = aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "",
neg_ctx->protocol, encoded);

View File

@ -455,8 +455,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
{
size_t size = 0;
char *base64 = NULL;
size_t base64_sz = 0;
unsigned char ntlmbuf[NTLM_BUFSIZE];
CURLcode res;
CURLcode error;
/* point to the address of the pointer that holds the string to sent to the
server, which is for a plain host or for a HTTP proxy */
@ -516,14 +517,19 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
/* Create a type-1 message */
res = Curl_ntlm_create_type1_message(userp, passwdp,
error = Curl_ntlm_create_type1_message(userp, passwdp,
ntlm, ntlmbuf, &size);
if(CURLE_OK == res) {
/* now size is the size of the base64 encoded package size */
size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
if(error)
return error;
if(size > 0) {
/* convert the binary blob into base64 */
error = Curl_base64_encode(NULL, (char *)ntlmbuf, size,
&base64, &base64_sz);
if(error)
return error;
if(base64_sz > 0) {
Curl_safefree(*allocuserpwd);
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
proxy ? "Proxy-" : "",
@ -532,35 +538,36 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
free(base64);
}
}
else
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
break;
case NTLMSTATE_TYPE2:
/* We already received the type-2 message, create a type-3 message */
res = Curl_ntlm_create_type3_message(conn->data, userp, passwdp,
error = Curl_ntlm_create_type3_message(conn->data, userp, passwdp,
ntlm, ntlmbuf, &size);
if(CURLE_OK == res) {
/* convert the binary blob into base64 */
size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
if(error)
return error;
if(size > 0) {
/* convert the binary blob into base64 */
error = Curl_base64_encode(NULL, (char *)ntlmbuf, size,
&base64, &base64_sz);
if(error)
return error;
if(base64_sz > 0) {
Curl_safefree(*allocuserpwd);
*allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
proxy ? "Proxy-" : "",
base64);
DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
free(base64);
}
}
else
return CURLE_OUT_OF_MEMORY; /* FIX TODO */
ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
authp->done = TRUE;
}
}
break;

View File

@ -201,7 +201,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
int ret;
char *p;
unsigned char *ptr;
size_t len;
size_t len = 0;
KTEXT_ST adat;
MSG_DAT msg_data;
int checksum;
@ -212,6 +212,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
int l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
CURLcode result;
size_t base64_sz = 0;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
@ -247,8 +248,10 @@ krb4_auth(void *app_data, struct connectdata *conn)
}
#endif
if(Curl_base64_encode(conn->data, (char *)adat.dat, adat.length, &p) < 1) {
Curl_failf(data, "Out of memory base64-encoding");
result = Curl_base64_encode(conn->data, (char *)adat.dat, adat.length,
&p, &base64_sz)
if(result) {
Curl_failf(data, "base64-encoding: %s", curl_easy_strerror(result));
return AUTH_CONTINUE;
}
@ -273,9 +276,14 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_ERROR;
}
p += 5;
len = Curl_base64_decode(p, &ptr);
result = Curl_base64_decode(p, &ptr, &len);
if(result) {
Curl_failf(data, "base64-decoding: %s", curl_easy_strerror(result));
return AUTH_ERROR;
}
if(len > sizeof(adat.dat)-1) {
free(ptr);
ptr = NULL;
len = 0;
}
if(!len || !ptr) {
@ -330,11 +338,12 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
char *name;
char *p;
char passwd[100];
size_t tmp;
size_t tmp = 0;
ssize_t nread;
enum protection_level save;
CURLcode result;
unsigned char *ptr;
size_t base64_sz = 0;
save = krb4_set_command_prot(conn, PROT_PRIVATE);
@ -360,9 +369,14 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
}
p += 2;
tmp = Curl_base64_decode(p, &ptr);
result = Curl_base64_decode(p, &ptr, &tmp);
if(result) {
Curl_failf(conn->data, "base64-decoding: %s", curl_easy_strerror(result));
return result;
}
if(tmp >= sizeof(tkt.dat)) {
free(ptr);
ptr = NULL;
tmp = 0;
}
if(!tmp || !ptr) {
@ -404,11 +418,12 @@ CURLcode Curl_krb_kauth(struct connectdata *conn)
memset(key, 0, sizeof(key));
memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd));
if(Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length, &p)
< 1) {
failf(conn->data, "Out of memory base64-encoding.");
result = Curl_base64_encode(conn->data, (char *)tktcopy.dat, tktcopy.length,
&p, &base64_sz)
if(result) {
Curl_failf(conn->data, "base64-encoding: %s", curl_easy_strerror(result));
krb4_set_command_prot(conn, save);
return CURLE_OUT_OF_MEMORY;
return result;
}
memset (tktcopy.dat, 0, tktcopy.length);

View File

@ -172,6 +172,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
gss_name_t gssname;
gss_ctx_id_t *context = app_data;
struct gss_channel_bindings_struct chan;
size_t base64_sz = 0;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)LOCAL_ADDR, &l) < 0)
@ -251,9 +252,10 @@ krb5_auth(void *app_data, struct connectdata *conn)
}
if(output_buffer.length != 0) {
if(Curl_base64_encode(data, (char *)output_buffer.value,
output_buffer.length, &p) < 1) {
Curl_infof(data, "Out of memory base64-encoding\n");
result = Curl_base64_encode(data, (char *)output_buffer.value,
output_buffer.length, &p, &base64_sz)
if(result) {
Curl_infof(data,"base64-encoding: %s\n", curl_easy_strerror(result));
ret = AUTH_CONTINUE;
break;
}
@ -281,10 +283,11 @@ krb5_auth(void *app_data, struct connectdata *conn)
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\n");
result = Curl_base64_decode(p + 5,
(unsigned char **)&_gssresp.value,
&_gssresp.length);
if(result) {
Curl_failf(data,"base64-decoding: %s", curl_easy_strerror(result));
ret = AUTH_CONTINUE;
break;
}

View File

@ -176,8 +176,8 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
struct SessionHandle *data=conn->data;
int ldap_proto = LDAP_VERSION3;
int ldap_ssl = 0;
char *val_b64;
size_t val_b64_sz;
char *val_b64 = NULL;
size_t val_b64_sz = 0;
curl_off_t dlsize = 0;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */
@ -405,10 +405,20 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
(char *)attribute +
(strlen((char *)attribute) - 7)) == 0)) {
/* Binary attribute, encode to base64. */
val_b64_sz = Curl_base64_encode(data,
CURLcode error = Curl_base64_encode(data,
vals[i]->bv_val,
vals[i]->bv_len,
&val_b64);
&val_b64,
&val_b64_sz);
if(error) {
ldap_value_free_len(vals);
ldap_memfree(attribute);
ldap_memfree(dn);
if(ber)
ber_free(ber, 0);
status = error;
goto quit;
}
if(val_b64_sz > 0) {
Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
free(val_b64);

View File

@ -544,12 +544,21 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
}
}
if(binary || binval) {
char *val_b64;
char *val_b64 = NULL;
size_t val_b64_sz = 0;
/* Binary value, encode to base64. */
size_t val_b64_sz = Curl_base64_encode(data,
CURLcode error = Curl_base64_encode(data,
bvals[i].bv_val,
bvals[i].bv_len,
&val_b64);
&val_b64,
&val_b64_sz);
if(error) {
ber_memfree(bvals);
ber_free(ber, 0);
ldap_msgfree(result);
*err = error;
return -1;
}
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
data->req.bytecount += 2;
if(val_b64_sz > 0) {

View File

@ -61,6 +61,7 @@
#include "ftp.h"
#include "sendf.h"
#include "rawstr.h"
#include "warnless.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -280,12 +281,13 @@ static ssize_t sec_recv(struct connectdata *conn, int sockindex,
static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
const char *from, int length)
{
size_t bytes;
size_t htonl_bytes;
char *buffer;
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;
bool iscmd = (prot_level == PROT_CMD)?TRUE:FALSE
DEBUGASSERT(prot_level > PROT_NONE && prot_level < PROT_LAST);
@ -297,9 +299,17 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
}
bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
(void**)&buffer, conn);
if(!buffer || bytes <= 0)
return; /* error */
if(iscmd) {
bytes = Curl_base64_encode(conn->data, buffer, bytes, &cmd_buffer);
if(bytes > 0) {
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)
@ -307,7 +317,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
else
socket_write(conn, fd, mic, 4);
socket_write(conn, fd, cmd_buffer, bytes);
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);
@ -317,7 +327,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
else {
htonl_bytes = htonl(bytes);
socket_write(conn, fd, &htonl_bytes, sizeof(htonl_bytes));
socket_write(conn, fd, buffer, bytes);
socket_write(conn, fd, buffer, curlx_sitouz(bytes));
}
free(buffer);
}
@ -362,14 +372,20 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
int decoded_len;
char *buf;
int ret_code;
size_t decoded_sz = 0;
CURLcode error;
DEBUGASSERT(level > PROT_NONE && level < PROT_LAST);
decoded_len = Curl_base64_decode(buffer + 4, (unsigned char **)&buf);
if(decoded_len <= 0) {
error = Curl_base64_decode(buffer + 4, (unsigned char **)&buf, &decoded_sz);
if(error || decoded_sz == 0)
return -1;
if(decoded_sz > (size_t)INT_MAX) {
free(buf);
return -1;
}
decoded_len = curlx_uztosi(decoded_sz);
decoded_len = conn->mech->decode(conn->app_data, buf, decoded_len,
level, conn);

View File

@ -341,7 +341,8 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
return CURLE_OK;
}
static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
static CURLcode smtp_auth_plain_data(struct connectdata *conn,
char **outptr, size_t *outlen)
{
char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH];
size_t ulen;
@ -350,8 +351,11 @@ static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
ulen = strlen(conn->user);
plen = strlen(conn->passwd);
if(2 * ulen + plen + 2 > sizeof plainauth)
return 0;
if(2 * ulen + plen + 2 > sizeof plainauth) {
*outlen = 0;
*outptr = NULL;
return CURLE_OUT_OF_MEMORY; /* plainauth too small */
}
memcpy(plainauth, conn->user, ulen);
plainauth[ulen] = '\0';
@ -359,21 +363,25 @@ static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
plainauth[2 * ulen + 1] = '\0';
memcpy(plainauth + 2 * ulen + 2, conn->passwd, plen);
return Curl_base64_encode(conn->data, plainauth, 2 * ulen + plen + 2,
outptr);
outptr, outlen);
}
static size_t smtp_auth_login_user(struct connectdata * conn, char * * outptr)
static CURLcode smtp_auth_login_user(struct connectdata *conn,
char **outptr, size_t *outlen)
{
size_t ulen;
ulen = strlen(conn->user);
size_t ulen = strlen(conn->user);
if(!ulen) {
*outptr = strdup("=");
return *outptr? 1: 0;
if(*outptr) {
*outlen = (size_t) 1;
return CURLE_OK;
}
*outlen = 0;
return CURLE_OUT_OF_MEMORY;
}
return Curl_base64_encode(conn->data, conn->user, ulen, outptr);
return Curl_base64_encode(conn->data, conn->user, ulen, outptr, outlen);
}
static CURLcode smtp_authenticate(struct connectdata *conn)
@ -409,13 +417,13 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
mech = "PLAIN";
state1 = SMTP_AUTHPLAIN;
state2 = SMTP_AUTH;
l = smtp_auth_plain_data(conn, &initresp);
result = smtp_auth_plain_data(conn, &initresp, &l);
}
else if(smtpc->authmechs & SMTP_AUTH_LOGIN) {
mech = "LOGIN";
state1 = SMTP_AUTHLOGIN;
state2 = SMTP_AUTHPASSWD;
l = smtp_auth_login_user(conn, &initresp);
result = smtp_auth_login_user(conn, &initresp, &l);
}
else {
infof(conn->data, "No known auth mechanisms supported!\n");
@ -423,24 +431,20 @@ static CURLcode smtp_authenticate(struct connectdata *conn)
}
if(!result) {
if(!l)
result = CURLE_OUT_OF_MEMORY;
else if(initresp &&
if(initresp &&
l + strlen(mech) <= 512 - 8) { /* AUTH <mech> ...<crlf> */
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
free(initresp);
if(!result)
state(conn, state2);
}
else {
Curl_safefree(initresp);
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
if(!result)
state(conn, state1);
}
Curl_safefree(initresp);
}
}
@ -571,8 +575,8 @@ static CURLcode smtp_state_authplain_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t l;
char * plainauth;
size_t l = 0;
char * plainauth = NULL;
(void)instate; /* no use for this yet */
@ -581,17 +585,17 @@ static CURLcode smtp_state_authplain_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED;
}
else {
l = smtp_auth_plain_data(conn, &plainauth);
result = smtp_auth_plain_data(conn, &plainauth, &l);
if(!l)
result = CURLE_OUT_OF_MEMORY;
else {
if(!result) {
if(plainauth) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
free(plainauth);
if(!result)
state(conn, SMTP_AUTH);
}
Curl_safefree(plainauth);
}
}
return result;
@ -604,8 +608,8 @@ static CURLcode smtp_state_authlogin_resp(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t l;
char * authuser;
size_t l = 0;
char * authuser = NULL;
(void)instate; /* no use for this yet */
@ -614,17 +618,17 @@ static CURLcode smtp_state_authlogin_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED;
}
else {
l = smtp_auth_login_user(conn, &authuser);
result = smtp_auth_login_user(conn, &authuser, &l);
if(!l)
result = CURLE_OUT_OF_MEMORY;
else {
if(!result) {
if(authuser) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
free(authuser);
if(!result)
state(conn, SMTP_AUTHPASSWD);
}
Curl_safefree(authuser);
}
}
return result;
@ -638,8 +642,8 @@ static CURLcode smtp_state_authpasswd_resp(struct connectdata *conn,
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t plen;
size_t l;
char *authpasswd;
size_t l = 0;
char *authpasswd = NULL;
(void)instate; /* no use for this yet */
@ -653,17 +657,17 @@ static CURLcode smtp_state_authpasswd_resp(struct connectdata *conn,
if(!plen)
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "=");
else {
l = Curl_base64_encode(data, conn->passwd, plen, &authpasswd);
result = Curl_base64_encode(data, conn->passwd, plen, &authpasswd, &l);
if(!l)
result = CURLE_OUT_OF_MEMORY;
else {
if(!result) {
if(authpasswd) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
free(authpasswd);
if(!result)
state(conn, SMTP_AUTH);
}
Curl_safefree(authpasswd);
}
}
}
@ -682,8 +686,8 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
char * chlg64 = data->state.buffer;
unsigned char * chlg;
size_t chlglen;
size_t l;
char * rplyb64;
size_t l = 0;
char * rplyb64 = NULL;
HMAC_context * ctxt;
unsigned char digest[16];
char reply[MAX_CURL_USER_LENGTH + 32 /* 2 * size of MD5 digest */ + 1];
@ -711,9 +715,9 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
if(++l) {
chlg64[l] = '\0';
chlglen = Curl_base64_decode(chlg64, &chlg);
if(!chlglen)
return CURLE_OUT_OF_MEMORY;
result = Curl_base64_decode(chlg64, &chlg, &chlglen);
if(result)
return result;
}
}
@ -723,17 +727,14 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
(unsigned int)(strlen(conn->passwd)));
if(!ctxt) {
if(chlg)
free(chlg);
Curl_safefree(chlg);
return CURLE_OUT_OF_MEMORY;
}
if(chlglen > 0)
Curl_HMAC_update(ctxt, chlg, (unsigned int)(chlglen));
if(chlg)
free(chlg);
Curl_safefree(chlg);
Curl_HMAC_final(ctxt, digest);
@ -746,17 +747,17 @@ static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
digest[12], digest[13], digest[14], digest[15]);
/* Encode it to base64 and send it. */
l = Curl_base64_encode(data, reply, 0, &rplyb64);
result = Curl_base64_encode(data, reply, 0, &rplyb64, &l);
if(!l)
result = CURLE_OUT_OF_MEMORY;
else {
if(!result) {
if(rplyb64) {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
free(rplyb64);
if(!result)
state(conn, SMTP_AUTH);
}
Curl_safefree(rplyb64);
}
return result;
}

View File

@ -268,6 +268,25 @@ size_t curlx_sotouz(curl_off_t sonum)
#endif
}
/*
** signed int to unsigned size_t
*/
size_t curlx_sitouz(int sinum)
{
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
DEBUGASSERT(sinum >= 0);
return (size_t) sinum;
#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
}
#if defined(__INTEL_COMPILER) && defined(__unix__)
int curlx_FD_ISSET(int fd, fd_set *fdset)

View File

@ -38,6 +38,8 @@ ssize_t curlx_uztosz(size_t uznum);
size_t curlx_sotouz(curl_off_t sonum);
size_t curlx_sitouz(int sinum);
#if defined(__INTEL_COMPILER) && defined(__unix__)
int curlx_FD_ISSET(int fd, fd_set *fdset);

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -166,7 +166,9 @@ static int appenddata(char **dst_buf, /* dest buffer */
if(src_b64) {
/* base64 decode the given buffer */
src_len = Curl_base64_decode(src_buf, &buf64.as_uchar);
int error = (int) Curl_base64_decode(src_buf, &buf64.as_uchar, &src_len);
if(error)
return GPE_OUT_OF_MEMORY;
src_buf = buf64.as_char;
if(!src_len || !src_buf) {
/*

View File

@ -45,63 +45,80 @@ UNITTEST_START
char *output;
unsigned char *decoded;
size_t rc;
size_t size = 0;
unsigned char anychar = 'x';
CURLcode rc;
rc = Curl_base64_encode(data, "i", 1, &output);
fail_unless( rc == 4 , "return code should be 4" );
rc = Curl_base64_encode(data, "i", 1, &output, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 4, "size should be 4");
verify_memory( output, "aQ==", 4);
Curl_safefree(output);
rc = Curl_base64_encode(data, "ii", 2, &output);
fail_unless( rc == 4 , "return code should be 4" );
rc = Curl_base64_encode(data, "ii", 2, &output, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 4, "size should be 4");
verify_memory( output, "aWk=", 4);
Curl_safefree(output);
rc = Curl_base64_encode(data, "iii", 3, &output);
fail_unless( rc == 4 , "return code should be 4" );
rc = Curl_base64_encode(data, "iii", 3, &output, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 4, "size should be 4");
verify_memory( output, "aWlp", 4);
Curl_safefree(output);
rc = Curl_base64_encode(data, "iiii", 4, &output);
fail_unless( rc == 8 , "return code should be 8" );
rc = Curl_base64_encode(data, "iiii", 4, &output, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 8, "size should be 8");
verify_memory( output, "aWlpaQ==", 8);
Curl_safefree(output);
/* 0 length makes it do strlen() */
rc = Curl_base64_encode(data, "iiii", 0, &output);
fail_unless( rc == 8 , "return code should be 8" );
rc = Curl_base64_encode(data, "iiii", 0, &output, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 8, "size should be 8");
verify_memory( output, "aWlpaQ==", 8);
Curl_safefree(output);
rc = Curl_base64_decode("aWlpaQ==", &decoded);
fail_unless(rc == 4, "return code should be 4");
rc = Curl_base64_decode("aWlpaQ==", &decoded, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 4, "size should be 4");
verify_memory(decoded, "iiii", 4);
Curl_safefree(decoded);
rc = Curl_base64_decode("aWlp", &decoded);
fail_unless(rc == 3, "return code should be 3");
rc = Curl_base64_decode("aWlp", &decoded, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 3, "size should be 3");
verify_memory(decoded, "iii", 3);
Curl_safefree(decoded);
rc = Curl_base64_decode("aWk=", &decoded);
fail_unless(rc == 2, "return code should be 2");
rc = Curl_base64_decode("aWk=", &decoded, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 2, "size should be 2");
verify_memory(decoded, "ii", 2);
Curl_safefree(decoded);
rc = Curl_base64_decode("aQ==", &decoded);
fail_unless(rc == 1, "return code should be 1");
rc = Curl_base64_decode("aQ==", &decoded, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 1, "size should be 1");
verify_memory(decoded, "i", 2);
Curl_safefree(decoded);
/* this is an illegal input */
decoded = NULL;
rc = Curl_base64_decode("aQ", &decoded);
fail_unless(rc == 0, "return code should be 0");
size = 1; /* not zero */
decoded = &anychar; /* not NULL */
rc = Curl_base64_decode("aQ", &decoded, &size);
/* return code indiferent, but output shall be as follows */
fail_unless(size == 0, "size should be 0");
fail_if(decoded, "returned pointer should be NULL");
/* this is garbage input that libcurl decodes as far as possible */
rc = Curl_base64_decode("a\x1f==", &decoded);
fail_unless(rc == 1, "return code should be 1");
size = 0;
decoded = NULL;
rc = Curl_base64_decode("a\x1f==", &decoded, &size);
fail_unless(rc == CURLE_OK, "return code should be CURLE_OK");
fail_unless(size == 1, "size should be 1");
fail_if(!decoded, "returned pointer should not be NULL");
Curl_safefree(decoded);
UNITTEST_STOP