IList<AuthenticationSecret> DetectLoginSecrets (byte[] buffer, int offset, int endIndex) { var secrets = new List<AuthenticationSecret> (); int index = offset; if (commandState == ImapAuthCommandState.LoginNewLine) return EmptyAuthSecrets; if (commandState == ImapAuthCommandState.Login) { if (SkipText ("LOGIN ", buffer, ref index, endIndex)) commandState = ImapAuthCommandState.UserName; if (index >= endIndex || commandState == ImapAuthCommandState.Error) return EmptyAuthSecrets; } if (commandState == ImapAuthCommandState.UserName) { if (SkipLoginToken (secrets, buffer, ref index, endIndex, (byte) ' ')) { commandState = ImapAuthCommandState.Password; ClearLoginTokenState (); } if (index >= endIndex || commandState == ImapAuthCommandState.Error) return secrets; } if (commandState == ImapAuthCommandState.Password) { if (SkipLoginToken (secrets, buffer, ref index, endIndex, (byte) '\r')) { commandState = ImapAuthCommandState.LoginNewLine; ClearLoginTokenState (); } } return secrets; }
IList<AuthenticationSecret> DetectAuthSecrets (byte[] buffer, int offset, int endIndex) { int index = offset; if (commandState == ImapAuthCommandState.Authenticate) { if (SkipText ("AUTHENTICATE ", buffer, ref index, endIndex)) commandState = ImapAuthCommandState.AuthMechanism; if (index >= endIndex || commandState == ImapAuthCommandState.Error) return EmptyAuthSecrets; } if (commandState == ImapAuthCommandState.AuthMechanism) { while (index < endIndex && buffer[index] != (byte) ' ' && buffer[index] != (byte) '\r') index++; if (index < endIndex) { if (buffer[index] == (byte) ' ') { commandState = ImapAuthCommandState.AuthToken; } else { commandState = ImapAuthCommandState.AuthNewLine; } index++; } if (index >= endIndex) return EmptyAuthSecrets; } if (commandState == ImapAuthCommandState.AuthNewLine) { if (buffer[index] == (byte) '\n') { commandState = ImapAuthCommandState.AuthToken; index++; } else { commandState = ImapAuthCommandState.Error; } if (index >= endIndex || commandState == ImapAuthCommandState.Error) return EmptyAuthSecrets; } int startIndex = index; while (index < endIndex && buffer[index] != (byte) '\r') index++; if (index < endIndex) commandState = ImapAuthCommandState.AuthNewLine; if (index == startIndex) return EmptyAuthSecrets; var secret = new AuthenticationSecret (startIndex, index - startIndex); return new AuthenticationSecret[] { secret }; }
bool SkipText (string text, byte[] buffer, ref int index, int endIndex) { while (index < endIndex && textIndex < text.Length) { if (buffer[index] != (byte) text[textIndex]) { commandState = ImapAuthCommandState.Error; break; } textIndex++; index++; } return textIndex == text.Length; }
public IList<AuthenticationSecret> DetectSecrets (byte[] buffer, int offset, int count) { if (!IsAuthenticating || commandState == ImapAuthCommandState.Error || count == 0) return EmptyAuthSecrets; int endIndex = offset + count; int index = offset; if (commandState == ImapAuthCommandState.None) { // skip over the tag while (index < endIndex && buffer[index] != (byte) ' ') index++; if (index < endIndex) { commandState = ImapAuthCommandState.Command; index++; } if (index >= endIndex) return EmptyAuthSecrets; } if (commandState == ImapAuthCommandState.Command) { switch ((char) buffer[index]) { case 'A': commandState = ImapAuthCommandState.Authenticate; textIndex = 1; index++; break; case 'L': commandState = ImapAuthCommandState.Login; textIndex = 1; index++; break; default: commandState = ImapAuthCommandState.Error; break; } if (index >= endIndex || commandState == ImapAuthCommandState.Error) return EmptyAuthSecrets; } if (commandState >= ImapAuthCommandState.Authenticate && commandState <= ImapAuthCommandState.AuthToken) return DetectAuthSecrets (buffer, index, endIndex); return DetectLoginSecrets (buffer, index, endIndex); }
bool SkipLoginToken (List<AuthenticationSecret> secrets, byte[] buffer, ref int index, int endIndex, byte sentinel) { int startIndex; if (tokenType == ImapLoginTokenType.None) { switch ((char) buffer[index]) { case '{': literalState = ImapLiteralState.Octets; tokenType = ImapLoginTokenType.Literal; index++; break; case '"': tokenType = ImapLoginTokenType.QString; index++; break; default: tokenType = ImapLoginTokenType.Atom; break; } } switch (tokenType) { case ImapLoginTokenType.Literal: return SkipLiteralToken (secrets, buffer, ref index, endIndex, sentinel); case ImapLoginTokenType.QString: if (qstringState != ImapQStringState.Complete) { startIndex = index; while (index < endIndex) { if (qstringState == ImapQStringState.Escaped) { qstringState = ImapQStringState.None; } else if (buffer[index] == (byte) '\\') { qstringState = ImapQStringState.Escaped; } else if (buffer[index] == (byte) '"') { qstringState = ImapQStringState.EndQuote; break; } index++; } if (index > startIndex) secrets.Add (new AuthenticationSecret (startIndex, index - startIndex)); if (qstringState == ImapQStringState.EndQuote) { qstringState = ImapQStringState.Complete; index++; } } if (index >= endIndex) return false; if (buffer[index] != sentinel) { commandState = ImapAuthCommandState.Error; return false; } index++; return true; default: startIndex = index; while (index < endIndex && buffer[index] != sentinel) index++; if (index > startIndex) secrets.Add (new AuthenticationSecret (startIndex, index - startIndex)); if (index >= endIndex) return false; index++; return true; } }