diff options
-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 |