aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Holme <steve_holme@hotmail.com>2012-06-03 17:06:48 +0100
committerSteve Holme <steve_holme@hotmail.com>2012-06-03 17:06:48 +0100
commitb5bb61ee697b9a12e37c15b3bcbad33d808961d5 (patch)
tree7894604ed4a75503798c06accd7d0da48e184cf0
parent69f01ec2d1f1186e28c781ae3efa65e146d8424f (diff)
pop3: Fixed an issue with changes introduced in commit c267c53017bc
Because pop3_endofresp() is called for each line of data yet is not passed the line and line length, so we have to use the data pointed to by pp->linestart_resp which contains the whole packet, the mechanisms were being detected in one call yet the function would be called for each line of data. Using curl with verbose mode enabled would show that one line of data would be received in response to the AUTH command, before the AUTH <mechanism> command was sent to the server and then the next few lines of the original AUTH command would be displayed before the response from the AUTH <mechanism> command. This would then cause problems when parsing the CRAM-MD5 challenge data as extra data was contained in the buffer. Changed the parsing so that each line is checked for the mechanisms and the function returns FALSE until the whole of the AUTH response has been processed.
-rw-r--r--lib/pop3.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/lib/pop3.c b/lib/pop3.c
index f0ee23967..81a51cf4a 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -216,38 +216,56 @@ static const struct Curl_handler Curl_handler_pop3s_proxy = {
static int pop3_endofresp(struct pingpong *pp, int *resp)
{
char *line = pp->linestart_resp;
- size_t len = pp->nread_resp;
+ size_t len = strlen(pp->linestart_resp);
struct connectdata *conn = pp->conn;
struct pop3_conn *pop3c = &conn->proto.pop3c;
size_t wordlen;
- if((len < 1 || memcmp("+", line, 1)) &&
- (len < 3 || memcmp("+OK", line, 3)) &&
- (len < 4 || memcmp("-ERR", line, 4)))
- return FALSE; /* Nothing for us */
+ /* Do we have an error response? */
+ if(len >= 4 && !memcmp("-ERR", line, 4)) {
+ *resp = '-';
- *resp = line[0]; /* + or - */
+ return FALSE;
+ }
- if(pop3c->state == POP3_AUTH && len >= 3 && !memcmp(line, "+OK", 3)) {
- line += 3;
- len -= 3;
+ /* Are we processing reponses to our AUTH command */
+ if(pop3c->state == POP3_AUTH) {
+ /* Advance past our positive response if necessary */
+ if(len >= 3 && !memcmp(line, "+OK", 3)) {
+ line += 3;
+ len -= 3;
+ }
+
+ /* Loop through the data line */
for(;;) {
while(len &&
(*line == ' ' || *line == '\t' ||
*line == '\r' || *line == '\n')) {
+ if(*line == '\n')
+ return FALSE;
+
line++;
len--;
}
- if(!len || *line == '.')
+ if(!len)
break;
+ /* Until we receive the terminating character */
+ if(*line == '.') {
+ *resp = '+';
+
+ return TRUE;
+ }
+
+ /* Extract the word */
for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
line[wordlen] != '\t' && line[wordlen] != '\r' &&
line[wordlen] != '\n';)
wordlen++;
+ /* Test the word for a matching authentication mechanism */
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
pop3c->authmechs |= SASL_AUTH_LOGIN;
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
@@ -268,6 +286,13 @@ static int pop3_endofresp(struct pingpong *pp, int *resp)
}
}
+ if((len < 1 || memcmp("+", line, 1)) &&
+ (len < 3 || memcmp("+OK", line, 3)))
+ return FALSE; /* Nothing for us */
+
+ /* Otherwise it's a positive response */
+ *resp = '+';
+
return TRUE;
}
@@ -500,7 +525,7 @@ static CURLcode pop3_state_auth_plain_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED;
}
else {
- result = Curl_sasl_create_plain_message(conn->data, conn->user,
+ result = Curl_sasl_create_plain_message(data, conn->user,
conn->passwd, &plainauth, &len);
if(!result) {
@@ -534,7 +559,7 @@ static CURLcode pop3_state_auth_login_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED;
}
else {
- result = Curl_sasl_create_login_message(conn->data, conn->user,
+ result = Curl_sasl_create_login_message(data, conn->user,
&authuser, &len);
if(!result) {
@@ -568,7 +593,7 @@ static CURLcode pop3_state_auth_login_password_resp(struct connectdata *conn,
result = CURLE_LOGIN_DENIED;
}
else {
- result = Curl_sasl_create_login_message(conn->data, conn->passwd,
+ result = Curl_sasl_create_login_message(data, conn->passwd,
&authpasswd, &len);
if(!result) {