Merge pull request #135 from avitex/improve-auth-parsing

Improve auth resp parsing
This commit is contained in:
Jon Gjengset 2019-09-03 10:11:10 -04:00 committed by GitHub
commit 4bbf320e2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 15 deletions

View file

@ -29,6 +29,7 @@ imap-proto = "0.8"
nom = "4.0"
base64 = "0.10"
chrono = "0.4"
lazy_static = "1.4"
[dev-dependencies]
lettre = "0.9"

View file

@ -6,6 +6,7 @@ use std::collections::HashSet;
use std::io::{Read, Write};
use std::net::{TcpStream, ToSocketAddrs};
use std::ops::{Deref, DerefMut};
use std::str;
use std::sync::mpsc;
use super::authenticator::Authenticator;
@ -346,13 +347,19 @@ impl<T: Read + Write> Client<T> {
ok_or_unauth_client_err!(self.readline(&mut line), self);
if line.starts_with(b"+ ") {
let data = ok_or_unauth_client_err!(
parse_authenticate_response(String::from_utf8(line).unwrap()),
let line_str = ok_or_unauth_client_err!(
match str::from_utf8(line.as_slice()) {
Ok(line_str) => Ok(line_str),
Err(e) => Err(Error::Parse(ParseError::DataNotUtf8(line, e))),
},
self
);
let data = ok_or_unauth_client_err!(parse_authenticate_response(line_str), self);
let challenge = ok_or_unauth_client_err!(
base64::decode(data.as_str())
.map_err(|e| Error::Parse(ParseError::Authentication(data, Some(e)))),
base64::decode(data).map_err(|e| Error::Parse(ParseError::Authentication(
data.to_string(),
Some(e)
))),
self
);
let raw_response = &authenticator.process(&challenge);

View file

@ -5,7 +5,7 @@ use std::fmt;
use std::io::Error as IoError;
use std::net::TcpStream;
use std::result;
use std::string::FromUtf8Error;
use std::str::Utf8Error;
use base64::DecodeError;
use bufstream::IntoInnerError as BufError;
@ -111,7 +111,7 @@ impl StdError for Error {
Error::Io(ref e) => Some(e),
Error::Tls(ref e) => Some(e),
Error::TlsHandshake(ref e) => Some(e),
Error::Parse(ParseError::DataNotUtf8(ref e)) => Some(e),
Error::Parse(ParseError::DataNotUtf8(_, ref e)) => Some(e),
_ => None,
}
}
@ -126,8 +126,8 @@ pub enum ParseError {
Unexpected(String),
/// The client could not find or decode the server's authentication challenge.
Authentication(String, Option<DecodeError>),
/// The client receive data that was not UTF-8 encoded.
DataNotUtf8(FromUtf8Error),
/// The client received data that was not UTF-8 encoded.
DataNotUtf8(Vec<u8>, Utf8Error),
}
impl fmt::Display for ParseError {
@ -144,7 +144,7 @@ impl StdError for ParseError {
ParseError::Invalid(_) => "Unable to parse status response",
ParseError::Unexpected(_) => "Encountered unexpected parsed response",
ParseError::Authentication(_, _) => "Unable to parse authentication response",
ParseError::DataNotUtf8(_) => "Unable to parse data as UTF-8 text",
ParseError::DataNotUtf8(_, _) => "Unable to parse data as UTF-8 text",
}
}

View file

@ -1,4 +1,5 @@
use imap_proto::{self, MailboxDatum, Response};
use lazy_static::lazy_static;
use regex::Regex;
use std::collections::HashSet;
use std::sync::mpsc;
@ -6,15 +7,19 @@ use std::sync::mpsc;
use super::error::{Error, ParseError, Result};
use super::types::*;
pub fn parse_authenticate_response(line: String) -> Result<String> {
let authenticate_regex = Regex::new("^\\+ (.*)\r\n").unwrap();
if let Some(cap) = authenticate_regex.captures_iter(line.as_str()).next() {
let data = cap.get(1).map(|x| x.as_str()).unwrap_or("");
return Ok(String::from(data));
lazy_static! {
static ref AUTH_RESP_REGEX: Regex = Regex::new("^\\+ (.*)\r\n").unwrap();
}
Err(Error::Parse(ParseError::Authentication(line, None)))
pub fn parse_authenticate_response(line: &str) -> Result<&str> {
if let Some(cap) = AUTH_RESP_REGEX.captures_iter(line).next() {
let data = cap.get(1).map(|x| x.as_str()).unwrap_or("");
return Ok(data);
}
Err(Error::Parse(ParseError::Authentication(
line.to_string(),
None,
)))
}
enum MapOrNot<T> {