or fakedefer. Previously the sender could discover that the message
had in fact been accepted.
+JH/38 Taint-track intermediate values from the peer in multi-stage authentation
+ sequences. Previously the input was not noted as being tainted; notably
+ this resulted in behaviour of LOGIN vs. PLAIN being inconsistent under
+ bad coding of authenticators.
+
Exim version 4.96
-----------------
/* For interface, see auths/README */
int
-auth_cram_md5_server(auth_instance *ablock, uschar *data)
+auth_cram_md5_server(auth_instance * ablock, uschar * data)
{
-auth_cram_md5_options_block *ob =
+auth_cram_md5_options_block * ob =
(auth_cram_md5_options_block *)(ablock->options_block);
-uschar *challenge = string_sprintf("<%d.%ld@%s>", getpid(),
+uschar * challenge = string_sprintf("<%d.%ld@%s>", getpid(),
(long int) time(NULL), primary_hostname);
-uschar *clear, *secret;
+uschar * clear, * secret;
uschar digest[16];
int i, rc, len;
/* Send the challenge, read the return */
if ((rc = auth_get_data(&data, challenge, Ustrlen(challenge))) != OK) return rc;
-if ((len = b64decode(data, &clear)) < 0) return BAD64;
+if ((len = b64decode(data, &clear, GET_TAINTED)) < 0) return BAD64;
/* The return consists of a user name, space-separated from the CRAM-MD5
digest, expressed in hex. Extract the user name and put it in $auth1 and $1.
if (!smtp_read_response(sx, buffer, buffsize, '3', timeout))
return FAIL;
-if (b64decode(buffer + 4, &challenge) < 0)
+if (b64decode(buffer + 4, &challenge, buffer + 4) < 0)
{
string_format(buffer, buffsize, "bad base 64 string in challenge: %s",
big_buffer + 4);
within a shortlived child */
int
-auth_cyrus_sasl_server(auth_instance *ablock, uschar *data)
+auth_cyrus_sasl_server(auth_instance * ablock, uschar * data)
{
-auth_cyrus_sasl_options_block *ob =
+auth_cyrus_sasl_options_block * ob =
(auth_cyrus_sasl_options_block *)(ablock->options_block);
-uschar *output, *out2, *input, *clear, *hname;
-uschar *debug = NULL; /* Stops compiler complaining */
+uschar * output, * out2, * input, * clear, * hname;
+uschar * debug = NULL; /* Stops compiler complaining */
sasl_callback_t cbs[] = {{SASL_CB_LIST_END, NULL, NULL}};
-sasl_conn_t *conn;
+sasl_conn_t * conn;
char * realm_expanded = NULL;
-int rc, firsttime = 1, clen, *negotiated_ssf_ptr = NULL, negotiated_ssf;
+int rc, firsttime = 1, clen, * negotiated_ssf_ptr = NULL, negotiated_ssf;
unsigned int inlen, outlen;
input = data;
if (inlen)
{
- if ((clen = b64decode(input, &clear)) < 0)
+ if ((clen = b64decode(input, &clear, input)) < 0)
return BAD64;
input = clear;
inlen = clen;
}
inlen = Ustrlen(input);
- HDEBUG(D_auth) debug = string_copy(input);
+ HDEBUG(D_auth) debug = string_copy_taint(input, GET_TAINTED);
if (inlen)
{
- if ((clen = b64decode(input, &clear)) < 0)
+ if ((clen = b64decode(input, &clear, GET_TAINTED)) < 0)
{
sasl_dispose(&conn);
sasl_done();
uschar * clear, * end;
int len;
- if ((len = b64decode(data, &clear)) < 0) return BAD64;
+ if ((len = b64decode(data, &clear, GET_TAINTED)) < 0) return BAD64;
DEBUG(D_auth) debug_printf("auth input decode:");
for (end = clear + len; clear < end && expand_nmax < EXPAND_MAXN; )
{
Returns: OK on success
BAD64 if response too large for buffer
CANCELLED if response is "*"
+
+NOTE: the data came from the wire so should be tainted - but
+big_buffer is not taint-tracked. EVERY CALLER needs to apply
+tainting.
*/
int
if ((rc = auth_get_data(&resp, challenge, Ustrlen(challenge))) != OK)
return rc;
-if ((len = b64decode(resp, &clear)) < 0)
+if ((len = b64decode(resp, &clear, GET_TAINTED)) < 0)
return BAD64;
end = clear + len;
/* Now that we know we'll continue, we put the received data into $auth<n>,
if possible. First, decode it: buffer+4 skips over the SMTP status code. */
-clear_len = b64decode(buffer+4, &clear);
+clear_len = b64decode(buffer+4, &clear, buffer+4);
/* If decoding failed, the default is to terminate the authentication, and
return FAIL, with the SMTP response still in the buffer. However, if client_
break;
case 1:
- gbufdesc_in.length = b64decode(from_client, USS &gbufdesc_in.value);
+ gbufdesc_in.length = b64decode(from_client, USS &gbufdesc_in.value, GET_TAINTED);
if (gclient)
{
maj_stat = gss_release_name(&min_stat, &gclient);
break;
case 3:
- gbufdesc_in.length = b64decode(from_client, USS &gbufdesc_in.value);
+ gbufdesc_in.length = b64decode(from_client, USS &gbufdesc_in.value, GET_TAINTED);
maj_stat = gss_unwrap(&min_stat,
gcontext,
&gbufdesc_in, /* data from client */
};
int
-b64decode(const uschar *code, uschar **ptr)
+b64decode(const uschar * code, uschar ** ptr, const void * proto_mem)
{
int x, y;
{
int l = Ustrlen(code);
- *ptr = result = store_get(1 + l/4 * 3 + l%4, code);
+ *ptr = result = store_get(1 + l/4 * 3 + l%4, proto_mem);
}
/* Each cycle of the loop handles a quantum of 4 input bytes. For the last
case EOP_BASE64D:
{
uschar * s;
- int len = b64decode(sub, &s);
+ int len = b64decode(sub, &s, sub);
if (len < 0)
{
expand_string_message = string_sprintf("string \"%s\" is not "
extern uschar *b64encode(const uschar *, int);
extern uschar *b64encode_taint(const uschar *, int, const void *);
-extern int b64decode(const uschar *, uschar **);
+extern int b64decode(const uschar *, uschar **, const void *);
extern int bdat_getc(unsigned);
extern uschar *bdat_getbuf(unsigned *);
extern BOOL bdat_hasc(void);
be interpreted as text. This is not included in the count. */
int
-lss_b64decode(uschar *code, uschar **ptr)
+lss_b64decode(uschar * code, uschar ** ptr)
{
-return b64decode(code, ptr);
+return b64decode(code, ptr, code);
}
void
pdkim_decode_base64(const uschar * str, blob * b)
{
-int dlen = b64decode(str, &b->data);
+int dlen = b64decode(str, &b->data, str);
if (dlen < 0) b->data = NULL;
b->len = dlen;
}
*s2 = '\0';
-if ((rc = b64decode(s1, &der.data) < 0))
+if ((rc = b64decode(s1, &der.data, s1) < 0))
return US"Bad PEM-DER b64 decode";
der.len = rc;
encoding = toupper((*q1ptr)[1]);
**endptr = 0;
if (encoding == 'B')
- dlen = b64decode(*q2ptr+1, dptrptr);
+ dlen = b64decode(*q2ptr+1, dptrptr, *q2ptr+1);
else if (encoding == 'Q')
dlen = rfc2047_qpdecode(*q2ptr+1, dptrptr);
**endptr = '?'; /* restore */