private void RefreshUser() {
			if (!this.User.RefreshByCookies(this.Request.Cookies)) {
				if (this.Request.Cookies[User.COOKIE_USERNAME] != null && this.Request.Cookies[User.COOKIE_USERNAME].Value == this.DefaultAdminUserName) {
					if (this.Request.Cookies[User.COOKIE_PASSWORD] != null && this.Request.Cookies[User.COOKIE_PASSWORD].Value == this.DefaultAdminUserPassword) {
						this._user = new User(this.Request.Cookies[User.COOKIE_USERNAME].Value, this.Request.Cookies[User.COOKIE_PASSWORD].Value, UserAuthorization.Administrator, UserStatus.Active);
					}
				}
			}
		}
Beispiel #2
0
		public ImapServer(TcpClient client, int imapSslPort) : base(client, imapSslPort) {
			this.Connected += (object sender, TcpRequestEventArgs e) => {
				if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) {
					logger.Debug("connected from remote [{0}:{1}] to local [{2}:{3}]",
						e.RemoteEndPoint.Address.ToString(),
					    e.RemoteEndPoint.Port,
					    e.LocalEndPoint.Address.ToString(),
					    e.LocalEndPoint.Port
					);
				}
				
				this.SendMessage("OK IMAP4rev1 Service Ready", "*");
			};
			
			this.Disconnected += (object sender, TcpRequestEventArgs e) => {
				if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) {
					logger.Debug("disconnected from remote [{0}:{1}] to local [{2}:{3}]",
						e.RemoteEndPoint.Address.ToString(),
					    e.RemoteEndPoint.Port,
					    e.LocalEndPoint.Address.ToString(),
					    e.LocalEndPoint.Port
					);
				}
			};
			
			this.LineReceived += (object sender, TcpLineReceivedEventArgs e) => {
				logger.Info(String.Format("[{0}:{1}] to [{2}:{3}] Received Line: \"{4}\"", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, this._localEndPoint.Address.ToString(), this._localEndPoint.Port, e.Line));
				
				switch(this._state) {
					case State.AuthenticateCramMD5:
						List<string> wordsCramMD5 = this.GetWordsFromBase64EncodedLine(e.Line);
						
						this._state = State.Default;
						if (wordsCramMD5.Count == 1) {
							string[] splittedWords = wordsCramMD5[0].Split(new char[] {' '});
							if (splittedWords.Length == 2) {
								bool nameExists = User.NameExists(splittedWords[0]);
								bool eMailExists = User.EMailExists(splittedWords[0]);
								if (nameExists || eMailExists) {
									string userId = (nameExists) ? User.GetIdByName(splittedWords[0]) : User.GetIdByEMail(splittedWords[0]);
									User tmpUser = new User();
									if (tmpUser.RefreshById(userId)) {
										string calculatedDigest = this.CalculateCramMD5Digest(tmpUser.Password, this._currentCramMD5Challenge);
										if (calculatedDigest == splittedWords[1]) {
											this._user = tmpUser;
											this.SendMessage("OK PLAIN AUTHENTICATION successful", this._lastClientId);
										} else {
											this.SendMessage("NO invalid authentication", this._lastClientId);
										}
									} else {
										this.SendMessage("NO invalid authentication", this._lastClientId);
									}
								} else {
									this.SendMessage("NO invalid authentication", this._lastClientId);
								}
							} else {
								this.SendMessage("NO invalid authentication", this._lastClientId);
							}
						} else {
							this.SendMessage("NO invalid authentication", this._lastClientId);
						}
						
						this._currentCramMD5Challenge = String.Empty;
						break;
						
					case State.AuthenticatePlain:
						List<string> words = new List<string>();
						try {
							words = this.GetWordsFromBase64EncodedLine(e.Line);
						} catch(Exception) {
							// maybe it is not base64-encoded
							Match plainTextMatch = Regex.Match(e.Line, "\\s+LOGIN\\s+\"([^\"]+)\"\\s+\"([^\"]+)\"", RegexOptions.IgnoreCase);
							if (plainTextMatch.Success) {
								words.Add(plainTextMatch.Groups[1].Value);
								words.Add(plainTextMatch.Groups[2].Value);
							}
						}
						
						this._state = State.Default;
						if (words.Count == 2) {
							if (words[0] != String.Empty && words[1] != String.Empty) {
								if (this._user.RefreshByUsernamePassword(words[0], words[1]) || this._user.RefreshByEMailPassword(words[0], words[1])) {
									this.SendMessage("OK PLAIN AUTHENTICATION successful", this._lastClientId);
								} else {
									this.SendMessage("NO invalid authentication", this._lastClientId);
								}
							} else {
								this.SendMessage("NO invalid authentication", this._lastClientId);
							}
						} else {
							this.SendMessage("NO invalid authentication", this._lastClientId);
						}
						break;
					
					case State.Default:
						Match clientCommandMatch = Regex.Match(e.Line, @"^([^\s]+)\s+(\w+)(\s.+)?", RegexOptions.IgnoreCase);
						if (clientCommandMatch.Success) {
							this._lastClientId = clientCommandMatch.Groups[1].Value;
		
							switch(clientCommandMatch.Groups[2].Value.ToUpper()) {
								case "AUTHENTICATE":
									this.Authenticate(clientCommandMatch.Groups[3].Value.Trim().ToUpper());
									break;
		
								case "CAPABILITY":
									string capabilities = "CAPABILITY IMAP4rev1 LOGIN";
									if (!this.SslIsActive) {
										capabilities += " STARTTLS";
									}
									capabilities += " AUTH=PLAIN";
									capabilities += " AUTH=CRAM-MD5";
									this.SendMessage(capabilities, "*");
									this.SendMessage("OK CAPABILITY completed", this._lastClientId);
									break;
								
								case "CHECK":
									this.SendMessage("OK CHECK completed", this._lastClientId);
									break;
									
								case "FETCH":
									this.Fetch();
									break;
								
								case "LOGOUT":
									this.Logout((TcpRequestHandler.TcpRequestHandler)sender);
									break;
									
								case "NOOP":
									this.SendMessage("OK NOOP completed", this._lastClientId);
									break;
									
								case "SELECT":
									this.Select(clientCommandMatch.Groups[3].Value.ToUpper());
									break;

								case "LSUB":
									Match lsubMatch = Regex.Match(clientCommandMatch.Groups[3].Value, "\"([^\"]*)\"\\s+\"([^\"]*)\"", RegexOptions.Compiled);
									if (lsubMatch.Success) {
										List<string> folders = this._user.GetFolders(lsubMatch.Groups[1].Value, lsubMatch.Groups[2].Value);
										foreach(string folder in folders) {
											this.SendMessage("LSUB () \"/\" \"" + folder + "\"", "*");
										}
									}
									this.SendMessage("OK LSUB completed", this._lastClientId);
									break;
								
								case "LIST":
									this.List(clientCommandMatch.Groups[3].Value.ToUpper());
									break;
								
								case "STARTTLS":
									this.SendMessage("OK Begin TLS negotiation now", this._lastClientId);
									if (this.StartTls()) {
										this.SendMessage("OK STARTTLS completed", this._lastClientId);
									} else {
										this.SendMessage("NO STARTTLS not supported", this._lastClientId);
									}
									break;
								
								case "UID":
									this.Uid(clientCommandMatch.Groups[3].Value.Trim());
									break;
								
								default:
									this.SendMessage("BAD " + clientCommandMatch.Groups[2].Value + " command not found", this._lastClientId);
									break;
							}
						} else {
							this.SendMessage("BAD invalid command line: " + e.Line, this._lastClientId);
						}
						break;
				}
			};
		}
		private bool Route(string file) {
			bool routed = false;

			switch(file) {
				case "/files/index.html":
					if (!this.User.IsLoggedIn) {
						this.Redirect("/login/");
						routed = true;
					}
					break;

				case "/files/logout.html":
					Cookie cookieUsername = new Cookie(User.COOKIE_USERNAME, "", "/");
					cookieUsername.Expired = true;
					cookieUsername.Expires = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
					Cookie cookiePassword = new Cookie(User.COOKIE_PASSWORD, "", "/");
					cookiePassword.Expired = true;
					cookiePassword.Expires = DateTime.Now.Subtract(new TimeSpan(1, 0, 0));
					this.Response.SetCookie(cookieUsername);
					this.Response.SetCookie(cookiePassword);
					this.Redirect("/");
					routed = true;
					break;
				
				case "/files/login.html":
					if (this.Request.HttpMethod == "POST") {
						using(HttpPostRequest.HttpPostRequest postRequest = new HttpPostRequest.HttpPostRequest(this.Request)) {
							if (postRequest.Parameters[User.COOKIE_USERNAME] != null && postRequest.Parameters[User.COOKIE_PASSWORD] != null) {
								User user = new User();
								if (user.RefreshByUsernamePassword(postRequest.Parameters[User.COOKIE_USERNAME], postRequest.Parameters[User.COOKIE_PASSWORD])) {
									this.Response.SetCookie(new Cookie(User.COOKIE_USERNAME, user.Username, "/"));
									this.Response.SetCookie(new Cookie(User.COOKIE_PASSWORD, user.Password, "/"));
									this.Redirect("/");
									routed = true;
								} else if (user.RefreshByEMailPassword(postRequest.Parameters[User.COOKIE_USERNAME], postRequest.Parameters[User.COOKIE_PASSWORD])) {
									this.Response.SetCookie(new Cookie(User.COOKIE_USERNAME, user.Username, "/"));
									this.Response.SetCookie(new Cookie(User.COOKIE_PASSWORD, user.Password, "/"));
									this.Redirect("/");
									routed = true;
								} else {
									if (postRequest.Parameters[User.COOKIE_USERNAME] == this.DefaultAdminUserName && postRequest.Parameters[User.COOKIE_PASSWORD] == this.DefaultAdminUserPassword) {
										user = new User(postRequest.Parameters[User.COOKIE_USERNAME], postRequest.Parameters[User.COOKIE_PASSWORD], UserAuthorization.Administrator, UserStatus.Active);
										this.Response.SetCookie(new Cookie(User.COOKIE_USERNAME, user.Username, "/"));
										this.Response.SetCookie(new Cookie(User.COOKIE_PASSWORD, user.Password, "/"));
										this.Redirect("/");
										routed = true;
									}
								}
							}
						}
					}
					break;
				
				case "/files/register.html":
					if (this.Request.HttpMethod == "POST") {
						using(HttpPostRequest.HttpPostRequest postRequest = new HttpPostRequest.HttpPostRequest(this.Request)) {
							if (postRequest.Parameters[User.COOKIE_USERNAME] != null && postRequest.Parameters[User.COOKIE_PASSWORD] != null && postRequest.Parameters["email_address"] != null) {
								if (!User.NameExists(postRequest.Parameters[User.COOKIE_USERNAME])) {
									if (!User.EMailExists(postRequest.Parameters["email_address"])) {
										User newUser = new User(postRequest.Parameters[User.COOKIE_USERNAME], postRequest.Parameters[User.COOKIE_PASSWORD], postRequest.Parameters["email_address"]);
										newUser.Add();
									}
								}
							}
						}
					}
					break;
			}

			return routed;
		}
Beispiel #4
0
		public void AssignToUser(User user) {
			if (this.SaveToMongoDB()) {
				this._user = user;
				MongoDatabase mongoDatabase = this._mongoServer.GetDatabase("email");
				MongoCollection mongoCollection = mongoDatabase.GetCollection<eMailEntity>("mails");
				IMongoQuery query = Query<eMailEntity>.Where(e => e.Id == new ObjectId(this.Id));
				mongoCollection.Remove(query);
			}
		}
Beispiel #5
0
		public void SetUser(User user) {
			this._user = user;
		}
Beispiel #6
0
		public SmtpServer(TcpClient client, int sslPort) : base(client, sslPort) {
			bool dataStarted = false;
			string mailMessage = String.Empty;

			eMail mail = new eMail();

			this.Connected += (object sender, TcpRequestEventArgs e) => {
				if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) {
					logger.Debug("connected from remote [{0}:{1}] to local [{2}:{3}]",
						e.RemoteEndPoint.Address.ToString(),
					    e.RemoteEndPoint.Port,
					    e.LocalEndPoint.Address.ToString(),
					    e.LocalEndPoint.Port
					);
				}

				this.SendMessage("service ready", 220);
			};
			
			this.Disconnected += (object sender, TcpRequestEventArgs e) => {
				if (this.Verbose && e.RemoteEndPoint != null && e.LocalEndPoint != null) {
					logger.Debug("disconnected from remote [{0}:{1}] to local [{2}:{3}]",
						e.RemoteEndPoint.Address.ToString(),
					    e.RemoteEndPoint.Port,
					    e.LocalEndPoint.Address.ToString(),
					    e.LocalEndPoint.Port
					);
				}
			};

			this.LineReceived += (object sender, TcpLineReceivedEventArgs e) => {
				logger.Info(String.Format("[{0}:{1}] to [{2}:{3}] Received Line: \"{4}\"", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, this._localEndPoint.Address.ToString(), this._localEndPoint.Port, e.Line));

				switch(this._state) {
					case State.AuthenticateLoginUsername:
						this._temporaryVariables["username"] = Encoding.UTF8.GetString(Convert.FromBase64String(e.Line)).Trim();
						if (this._temporaryVariables["username"] != String.Empty) {
							this._state = State.AuthenticateLoginPassword;

							if (User.NameExists(this._temporaryVariables["username"]) || User.EMailExists(this._temporaryVariables["username"])) {
								this.SendMessage(Convert.ToBase64String(Encoding.UTF8.GetBytes("Password:"******"5.7.8 Authentication credentials invalid", 535);
							}
						} else {
							this._temporaryVariables.Remove("username");
							this._state = State.Default;
							this.SendMessage("5.7.8 Authentication credentials invalid", 535);
						}
						break;
					
					case State.AuthenticateLoginPassword:
						this._temporaryVariables["password"] = Encoding.UTF8.GetString(Convert.FromBase64String(e.Line)).Trim();
						this._state = State.Default;
						if (this._temporaryVariables["password"] != String.Empty) {
							string username = this._temporaryVariables["username"];
							string password = this._temporaryVariables["password"];
							this._temporaryVariables.Remove("username");
							this._temporaryVariables.Remove("password");

							if (this._user.RefreshByUsernamePassword(username, password) || this._user.RefreshByEMailPassword(username, password)) {
								this.SendMessage("2.7.0 Authentication Succeeded", 235);
							} else {
								this.SendMessage("5.7.8 Authentication credentials invalid", 535);
							}
						} else {
							this.SendMessage("5.7.8 Authentication credentials invalid", 535);
						}
						break;
					
					case State.AuthenticateCramMD5:
						List<string> wordsCramMD5 = this.GetWordsFromBase64EncodedLine(e.Line);
						
						this._state = State.Default;
						if (wordsCramMD5.Count == 1) {
							string[] splittedWords = wordsCramMD5[0].Split(new char[] {' '});
							if (splittedWords.Length == 2) {
								bool nameExists = User.NameExists(splittedWords[0]);
								bool eMailExists = User.EMailExists(splittedWords[0]);
								if (nameExists || eMailExists) {
									string userId = (nameExists) ? User.GetIdByName(splittedWords[0]) : User.GetIdByEMail(splittedWords[0]);
									User tmpUser = new User();
									if (tmpUser.RefreshById(userId)) {
										string calculatedDigest = this.CalculateCramMD5Digest(tmpUser.Password, this._currentCramMD5Challenge);
										if (calculatedDigest == splittedWords[1]) {
											this._user = tmpUser;
											this.SendMessage("2.7.0 Authentication Succeeded", 235);
										} else {
											this.SendMessage("5.7.8 Authentication credentials invalid", 535);
										}
									} else {
										this.SendMessage("4.7.0 Temporary authentication failure", 454);
									}
								} else {
									this.SendMessage("5.7.8 Authentication credentials invalid", 535);
								}
							} else {
								this.SendMessage("5.7.8 Authentication credentials invalid", 535);
							}
						} else {
							this.SendMessage("5.7.8 Authentication credentials invalid", 535);
						}
						
						this._currentCramMD5Challenge = String.Empty;
						break;

					case State.Default:
					default:
						if (!dataStarted) {
							if (e.Line.StartsWith("HELO ")) {
								mail.SetClientName(e.Line.Substring(5));
								this.SendMessage("OK", 250);
							} else if (e.Line.StartsWith("EHLO ")) {
								mail.SetClientName(e.Line.Substring(5));
								this.SendMessage("Hello " + mail.ClientName + " [" + this._remoteEndPoint.Address.ToString() + "]", "250-localhost");
								if (!this.SslIsActive) {
									string capabilities = "LOGIN";
									capabilities += " PLAIN CRAM-MD5";
									this.SendMessage(capabilities, "250-AUTH");
									this.SendMessage("STARTTLS", 250);
								} else {
									string capabilities = "AUTH LOGIN";
									capabilities += " PLAIN CRAM-MD5";
									this.SendMessage(capabilities, 250);
								}
							} else if (e.Line.StartsWith("AUTH ")) {
								Match authMatch = Regex.Match(e.Line, @"^AUTH\s+(PLAIN|CRAM-MD5|LOGIN)(.*)?", RegexOptions.IgnoreCase);
								if (authMatch.Success) {
									switch(authMatch.Groups[1].Value.ToUpper()) {
										case "PLAIN":
											List<string> words = new List<string>();
											try {
												words = this.GetWordsFromBase64EncodedLine(authMatch.Groups[2].Value);
											} catch(Exception) {

											}
						
											this._state = State.Default;
											if (words.Count == 2) {
												if (words[0] != String.Empty && words[1] != String.Empty) {
													if (this._user.RefreshByUsernamePassword(words[0], words[1]) || this._user.RefreshByEMailPassword(words[0], words[1])) {
														this.SendMessage("2.7.0 Authentication Succeeded", 235);
													} else {
														this.SendMessage("5.7.8 Authentication credentials invalid", 535);
													}
												} else {
													this.SendMessage("5.7.8 Authentication credentials invalid", 535);
												}
											} else {
												this.SendMessage("5.7.8 Authentication credentials invalid", 535);
											}
											break;
										
										case "LOGIN":
											this._state = State.AuthenticateLoginUsername;
											this.SendMessage(Convert.ToBase64String(Encoding.UTF8.GetBytes("Username:"******"CRAM-MD5":
											this._state = State.AuthenticateCramMD5;
											string base64EncodedCramMD5Challenge = this.CalculateOneTimeBase64Challenge("localhost.de");
											this._currentCramMD5Challenge = Encoding.UTF8.GetString(Convert.FromBase64String(base64EncodedCramMD5Challenge));
											this.SendMessage(base64EncodedCramMD5Challenge, 334);
											break;

										default:
											this.SendMessage("Unrecognized authentication type", 504);
											break;
									}
								}
							} else if (e.Line.StartsWith("MAIL FROM:")) {
								string email = e.Line.Substring(10);
								try {
									mail.SetFrom(email);
									this.SendMessage("OK", 250);
								} catch(FormatException) {
									this.SendMessage("BAD <" + email + ">... Denied due to invalid email-format", 555);
								}
							} else if (e.Line.StartsWith("RCPT TO:")) {
								mail.SetRecipient(e.Line.Substring(8));
								this.SendMessage("OK", 250);
							} else if (e.Line.StartsWith("STARTTLS")) {
								if (e.Line.Trim() == "STARTTLS") {
									this.SendMessage("Ready to start TLS", 220);
									if (!this.StartTls()) {
										this.SendMessage("TLS not available due to temporary reason", 454);
									}
								} else {
									this.SendMessage("Syntax error (no parameters allowed)", 501);
								}
							} else if (e.Line == "DATA") {
								this.SendMessage("start mail input", 354);
								dataStarted = true;
							} else if (e.Line == "QUIT") {
								if (eMailServer.Options.Verbose) {
									logger.Debug("[{0}:{1}] to [{2}:{3}] quit connection", this._localEndPoint.Address.ToString(), this._localEndPoint.Port, this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port);
								}
								this.Close();
								return;
							} else {
								this.SendMessage("Syntax error, command unrecognized", 500);
								if (eMailServer.Options.Verbose) {
									logger.Debug("[{0}:{1}] to [{2}:{3}] unknown command: {2}", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, this._localEndPoint.Address.ToString(), this._localEndPoint.Port, e.Line);
								}
							}
						} else {
							if (e.Line == ".") {
								mailMessage = mailMessage.Trim();
								logger.Info("[{0}:{1}] to [{2}:{3}] eMail data received: {2}", this._remoteEndPoint.Address.ToString(), this._remoteEndPoint.Port, mailMessage, this._localEndPoint.Address.ToString(), this._localEndPoint.Port);
								dataStarted = false;

								mail.ParseData(mailMessage);
								if (mail.IsValid) {
									if (this._user.IsLoggedIn && User.EMailExists(mail.MailFrom)) {
										mail.SetUser(this._user);
										mail.SetFolder("SENT");
									} else {
										mail.SetFolder("INBOX");
									}

									mail.SaveToMongoDB();
								} else {
									logger.Error("received message is invalid for saving to database.");
								}

								this.SendMessage("OK", 250);
							} else {
								mailMessage += e.Line + "\r\n";
							}
						}
						break;
				}
			};
		}
		private static void Check() {
			Console.WriteLine("running precheck...");
			
			MongoServer mongoServer = MyMongoDB.GetServer();
			
			MongoDatabase mongoDatabase = mongoServer.GetDatabase("email");
			MongoCollection<LazyBsonDocument> mongoCollection = mongoDatabase.GetCollection<LazyBsonDocument>("mails");
			
			MongoCursor<LazyBsonDocument> mongoCursor = mongoCollection.FindAll();
			foreach(LazyBsonDocument bsonDocument in mongoCursor) {
				if (Options.Verbose) {
					Console.WriteLine("checking email-id: " + bsonDocument["_id"].ToString());
				}
				try {
					if (User.EMailExists(bsonDocument["RecipientTo"].AsString)) {
						Console.WriteLine("user with email-address found: " + bsonDocument["RecipientTo"].AsString);
						User newMailUser = new User();
						newMailUser.RefreshById(User.GetIdByEMail(bsonDocument["RecipientTo"].AsString));
						eMail mail = new eMail(bsonDocument);
						mail.AssignToUser(newMailUser);
					}
				} catch(Exception ex) {
					logger.ErrorException(ex.Message, ex);
				}
			}
			
			Console.WriteLine("precheck finished...");
		}