diff options
author | Yang Tse <yangsita@gmail.com> | 2011-08-24 08:07:36 +0200 |
---|---|---|
committer | Yang Tse <yangsita@gmail.com> | 2011-08-24 08:10:30 +0200 |
commit | fd00b382b2d33ef90c6f5c840a32b66c8ceb1662 (patch) | |
tree | e95c73f96e5b4e67059326823e68ce78fc6f300b | |
parent | cce6508242ab73cca896788ad9f968b89e5f9f3a (diff) |
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.
-rw-r--r-- | lib/base64.c | 64 | ||||
-rw-r--r-- | lib/curl_base64.h | 11 | ||||
-rw-r--r-- | lib/curl_ntlm.c | 16 | ||||
-rw-r--r-- | lib/http.c | 36 | ||||
-rw-r--r-- | lib/http_digest.c | 13 | ||||
-rw-r--r-- | lib/http_negotiate.c | 33 | ||||
-rw-r--r-- | lib/http_negotiate_sspi.c | 25 | ||||
-rw-r--r-- | lib/http_ntlm.c | 45 | ||||
-rw-r--r-- | lib/krb4.c | 39 | ||||
-rw-r--r-- | lib/krb5.c | 17 | ||||
-rw-r--r-- | lib/ldap.c | 24 | ||||
-rw-r--r-- | lib/openldap.c | 19 | ||||
-rw-r--r-- | lib/security.c | 36 | ||||
-rw-r--r-- | lib/smtp.c | 135 | ||||
-rw-r--r-- | lib/warnless.c | 19 | ||||
-rw-r--r-- | lib/warnless.h | 2 | ||||
-rw-r--r-- | tests/server/getpart.c | 6 | ||||
-rw-r--r-- | tests/unit/unit1302.c | 65 |
18 files changed, 380 insertions, 225 deletions
diff --git a/lib/base64.c b/lib/base64.c index 812fd67c2..23ebb4aa9 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -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, - const char *inputbuff, size_t insize, - char **outptr) +CURLcode Curl_base64_encode(struct SessionHandle *data, + const char *inputbuff, size_t insize, + 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 ---- */ diff --git a/lib/curl_base64.h b/lib/curl_base64.h index 2498a0a22..6e200d2ec 100644 --- a/lib/curl_base64.h +++ b/lib/curl_base64.h @@ -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, - const char *inputbuff, size_t insize, - char **outptr); +CURLcode Curl_base64_encode(struct SessionHandle *data, + const char *inputbuff, size_t insize, + 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 */ diff --git a/lib/curl_ntlm.c b/lib/curl_ntlm.c index c0289e5d4..b555f5ab6 100644 --- a/lib/curl_ntlm.c +++ b/lib/curl_ntlm.c @@ -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); diff --git a/lib/http.c b/lib/http.c index 4952ddd64..edf3e163f 100644 --- a/lib/http.c +++ b/lib/http.c @@ -231,11 +231,13 @@ static char *copy_header_value(const char *h) */ static CURLcode http_output_basic(struct connectdata *conn, bool proxy) { - char *authorization; - struct SessionHandle *data=conn->data; + 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); - *userp = aprintf( "%sAuthorization: Basic %s\r\n", - proxy?"Proxy-":"", - authorization); - free(authorization); - if(!*userp) - return CURLE_OUT_OF_MEMORY; - } - else + + 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; + return CURLE_OK; } diff --git a/lib/http_digest.c b/lib/http_digest.c index 3ca0389e9..b41e62306 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -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)) - d->cnonce = cnonce; - else - return CURLE_OUT_OF_MEMORY; + + rc = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf), + &cnonce, &cnonce_sz); + if(rc) + return rc; + d->cnonce = cnonce; } /* diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index b3d870c9c..f0cf16b9e 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -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, - neg_ctx->output_token.value, - neg_ctx->output_token.length, - &encoded); + error = Curl_base64_encode(conn->data, + neg_ctx->output_token.value, + neg_ctx->output_token.length, + &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); diff --git a/lib/http_negotiate_sspi.c b/lib/http_negotiate_sspi.c index 875ed3cfd..08d016274 100644 --- a/lib/http_negotiate_sspi.c +++ b/lib/http_negotiate_sspi.c @@ -82,7 +82,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy, { struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg: &conn->data->state.negotiate; - BYTE *input_token = 0; + BYTE *input_token = 0; SecBufferDesc out_buff_desc; SecBuffer out_sec_buff; SecBufferDesc in_buff_desc; @@ -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, - (const char*)neg_ctx->output_token, - neg_ctx->output_token_length, - &encoded); + error = Curl_base64_encode(conn->data, + (const char*)neg_ctx->output_token, + neg_ctx->output_token_length, + &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); diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c index 2c60e5275..c5ee679a9 100644 --- a/lib/http_ntlm.c +++ b/lib/http_ntlm.c @@ -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, - ntlm, ntlmbuf, &size); + error = Curl_ntlm_create_type1_message(userp, passwdp, + ntlm, ntlmbuf, &size); + if(error) + return error; - 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(size > 0) { + /* convert the binary blob into base64 */ + error = Curl_base64_encode(NULL, (char *)ntlmbuf, size, + &base64, &base64_sz); + if(error) + return error; - if(size > 0) { + 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, - ntlm, ntlmbuf, &size); + error = Curl_ntlm_create_type3_message(conn->data, userp, passwdp, + ntlm, ntlmbuf, &size); + if(error) + return error; - if(CURLE_OK == res) { + if(size > 0) { /* convert the binary blob into base64 */ - size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64); + error = Curl_base64_encode(NULL, (char *)ntlmbuf, size, + &base64, &base64_sz); + if(error) + return error; - if(size > 0) { + 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); + + ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ + authp->done = TRUE; } } - else - return CURLE_OUT_OF_MEMORY; /* FIX TODO */ - - ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ - authp->done = TRUE; break; diff --git a/lib/krb4.c b/lib/krb4.c index 30b1c664e..2c5676a63 100644 --- a/lib/krb4.c +++ b/lib/krb4.c @@ -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,10 +276,15 @@ 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); - len=0; + ptr = NULL; + len = 0; } if(!len || !ptr) { Curl_failf(data, "Failed to decode base64 from server"); @@ -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,10 +369,15 @@ 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); - tmp=0; + ptr = NULL; + tmp = 0; } if(!tmp || !ptr) { Curl_failf(conn->data, "Failed to decode base64 in reply"); @@ -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); diff --git a/lib/krb5.c b/lib/krb5.c index 0422cda35..c5f635c1e 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -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; } diff --git a/lib/ldap.c b/lib/ldap.c index 9692ed9d7..0fcbc22e0 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -176,9 +176,9 @@ 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; - curl_off_t dlsize=0; + 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 */ #endif @@ -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, - vals[i]->bv_val, - vals[i]->bv_len, - &val_b64); + CURLcode error = Curl_base64_encode(data, + vals[i]->bv_val, + vals[i]->bv_len, + &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); diff --git a/lib/openldap.c b/lib/openldap.c index 69523cb37..070892524 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -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, - bvals[i].bv_val, - bvals[i].bv_len, - &val_b64); + CURLcode error = Curl_base64_encode(data, + bvals[i].bv_val, + bvals[i].bv_len, + &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) { diff --git a/lib/security.c b/lib/security.c index af61f3aed..595a7337e 100644 --- a/lib/security.c +++ b/lib/security.c @@ -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); diff --git a/lib/smtp.c b/lib/smtp.c index 5fa989346..9550c0fcc 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -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 && - l + strlen(mech) <= 512 - 8) { /* AUTH <mech> ...<crlf> */ + 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,16 +585,16 @@ 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 { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth); - free(plainauth); + if(!result) { + if(plainauth) { + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth); - if(!result) - state(conn, SMTP_AUTH); + if(!result) + state(conn, SMTP_AUTH); + } + Curl_safefree(plainauth); } } @@ -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,16 +618,16 @@ 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 { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser); - free(authuser); + if(!result) { + if(authuser) { + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser); - if(!result) - state(conn, SMTP_AUTHPASSWD); + if(!result) + state(conn, SMTP_AUTHPASSWD); + } + Curl_safefree(authuser); } } @@ -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,16 +657,16 @@ 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 { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd); - free(authpasswd); + if(!result) { + if(authpasswd) { + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd); - if(!result) - state(conn, SMTP_AUTH); + 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,16 +747,16 @@ 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 { - result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); - free(rplyb64); + if(!result) { + if(rplyb64) { + result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64); - if(!result) - state(conn, SMTP_AUTH); + if(!result) + state(conn, SMTP_AUTH); + } + Curl_safefree(rplyb64); } return result; diff --git a/lib/warnless.c b/lib/warnless.c index 37d15ce87..0f5fb5f4d 100644 --- a/lib/warnless.c +++ b/lib/warnless.c @@ -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) diff --git a/lib/warnless.h b/lib/warnless.h index 9ac59ac29..27cf57c31 100644 --- a/lib/warnless.h +++ b/lib/warnless.h @@ -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); diff --git a/tests/server/getpart.c b/tests/server/getpart.c index 743cb21b9..2351e1cc3 100644 --- a/tests/server/getpart.c +++ b/tests/server/getpart.c @@ -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) { /* diff --git a/tests/unit/unit1302.c b/tests/unit/unit1302.c index 7a61ec062..fc50c8865 100644 --- a/tests/unit/unit1302.c +++ b/tests/unit/unit1302.c @@ -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 |