1 /*
2   KeePass Password Safe - The Open-Source Password Manager
3   Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de>
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19 
20 using System;
21 using System.Collections.Generic;
22 using System.ComponentModel;
23 using System.Diagnostics;
24 using System.Net;
25 using System.Xml.Serialization;
26 
27 using KeePassLib.Delegates;
28 using KeePassLib.Interfaces;
29 using KeePassLib.Serialization;
30 
31 namespace KeePassLib
32 {
33 	/// <summary>
34 	/// Contains KeePassLib-global definitions and enums.
35 	/// </summary>
36 	public static class PwDefs
37 	{
38 		/// <summary>
39 		/// The product name.
40 		/// </summary>
41 		public static readonly string ProductName = "KeePass Password Safe";
42 
43 		/// <summary>
44 		/// A short, simple string representing the product name. The string
45 		/// should contain no spaces, directory separator characters, etc.
46 		/// </summary>
47 		public static readonly string ShortProductName = "KeePass";
48 
49 		internal const string UnixName = "keepass2";
50 		internal const string ResClass = "KeePass2"; // With initial capital
51 
52 		/// <summary>
53 		/// Version, encoded as 32-bit unsigned integer.
54 		/// 2.00 = 0x02000000, 2.01 = 0x02000100, ..., 2.18 = 0x02010800.
55 		/// As of 2.19, the version is encoded component-wise per byte,
56 		/// e.g. 2.19 = 0x02130000.
57 		/// It is highly recommended to use <c>FileVersion64</c> instead.
58 		/// </summary>
59 		public static readonly uint Version32 = 0x02310000;
60 
61 		/// <summary>
62 		/// Version, encoded as 64-bit unsigned integer
63 		/// (component-wise, 16 bits per component).
64 		/// </summary>
65 		public static readonly ulong FileVersion64 = 0x0002003100000000UL;
66 
67 		/// <summary>
68 		/// Version, encoded as string.
69 		/// </summary>
70 		public static readonly string VersionString = "2.49";
71 
72 		public static readonly string Copyright = @"Copyright © 2003-2021 Dominik Reichl";
73 
74 		/// <summary>
75 		/// Product website URL. Terminated by a forward slash.
76 		/// </summary>
77 		public static readonly string HomepageUrl = "https://keepass.info/";
78 
79 		/// <summary>
80 		/// URL to the online translations page.
81 		/// </summary>
82 		public static readonly string TranslationsUrl = "https://keepass.info/translations.html";
83 
84 		/// <summary>
85 		/// URL to the online plugins page.
86 		/// </summary>
87 		public static readonly string PluginsUrl = "https://keepass.info/plugins.html";
88 
89 		/// <summary>
90 		/// Product donations URL.
91 		/// </summary>
92 		public static readonly string DonationsUrl = "https://keepass.info/donate.html";
93 
94 		/// <summary>
95 		/// URL to the root path of the online KeePass help. Terminated by
96 		/// a forward slash.
97 		/// </summary>
98 		public static readonly string HelpUrl = "https://keepass.info/help/";
99 
100 		/// <summary>
101 		/// URL to a TXT file (eventually compressed) that contains information
102 		/// about the latest KeePass version available on the website.
103 		/// </summary>
104 		public static readonly string VersionUrl = "https://www.dominik-reichl.de/update/version2x.txt.gz";
105 
106 		/// <summary>
107 		/// A <c>DateTime</c> object that represents the time when the assembly
108 		/// was loaded.
109 		/// </summary>
110 		public static readonly DateTime DtDefaultNow = DateTime.UtcNow;
111 
112 		/// <summary>
113 		/// Default number of master key encryption/transformation rounds
114 		/// (making dictionary attacks harder).
115 		/// </summary>
116 		public static readonly ulong DefaultKeyEncryptionRounds = 60000;
117 
118 		/// <summary>
119 		/// Default identifier string for the title field.
120 		/// Should not contain spaces, tabs or other whitespace.
121 		/// </summary>
122 		public const string TitleField = "Title";
123 		// Const instead of static readonly for backward compatibility with plugins
124 
125 		/// <summary>
126 		/// Default identifier string for the user name field.
127 		/// Should not contain spaces, tabs or other whitespace.
128 		/// </summary>
129 		public const string UserNameField = "UserName";
130 		// Const instead of static readonly for backward compatibility with plugins
131 
132 		/// <summary>
133 		/// Default identifier string for the password field.
134 		/// Should not contain spaces, tabs or other whitespace.
135 		/// </summary>
136 		public const string PasswordField = "Password";
137 		// Const instead of static readonly for backward compatibility with plugins
138 
139 		/// <summary>
140 		/// Default identifier string for the URL field.
141 		/// Should not contain spaces, tabs or other whitespace.
142 		/// </summary>
143 		public const string UrlField = "URL";
144 		// Const instead of static readonly for backward compatibility with plugins
145 
146 		/// <summary>
147 		/// Default identifier string for the notes field.
148 		/// Should not contain spaces, tabs or other whitespace.
149 		/// </summary>
150 		public const string NotesField = "Notes";
151 		// Const instead of static readonly for backward compatibility with plugins
152 
153 		/// <summary>
154 		/// Default identifier string for the field which will contain TAN indices.
155 		/// </summary>
156 		public static readonly string TanIndexField = UserNameField;
157 
158 		/// <summary>
159 		/// Default title of an entry that is really a TAN entry.
160 		/// </summary>
161 		public static readonly string TanTitle = @"<TAN>";
162 
163 		/// <summary>
164 		/// Prefix of a custom auto-type string field.
165 		/// </summary>
166 		public static readonly string AutoTypeStringPrefix = "S:";
167 
168 		/// <summary>
169 		/// Default string representing a hidden password.
170 		/// </summary>
171 		public static readonly string HiddenPassword = "********";
172 
173 		/// <summary>
174 		/// Default auto-type keystroke sequence. If no custom sequence is
175 		/// specified, this sequence is used.
176 		/// </summary>
177 		public static readonly string DefaultAutoTypeSequence = @"{USERNAME}{TAB}{PASSWORD}{ENTER}";
178 
179 		/// <summary>
180 		/// Default auto-type keystroke sequence for TAN entries. If no custom
181 		/// sequence is specified, this sequence is used.
182 		/// </summary>
183 		public static readonly string DefaultAutoTypeSequenceTan = @"{PASSWORD}";
184 
185 		/// <summary>
186 		/// Maximum time (in milliseconds) after which the user interface
187 		/// should be updated.
188 		/// </summary>
189 		internal const int UIUpdateDelay = 50;
190 
191 		internal const uint QualityBitsWeak = 79;
192 
193 		internal const string FavoriteTag = "Favorite";
194 
195 		/// <summary>
196 		/// Check if a name is a standard field name.
197 		/// </summary>
198 		/// <param name="strFieldName">Input field name.</param>
199 		/// <returns>Returns <c>true</c>, if the field name is a standard
200 		/// field name (title, user name, password, ...), otherwise <c>false</c>.</returns>
IsStandardField(string strFieldName)201 		public static bool IsStandardField(string strFieldName)
202 		{
203 			Debug.Assert(strFieldName != null); if(strFieldName == null) return false;
204 
205 			if(strFieldName.Equals(TitleField)) return true;
206 			if(strFieldName.Equals(UserNameField)) return true;
207 			if(strFieldName.Equals(PasswordField)) return true;
208 			if(strFieldName.Equals(UrlField)) return true;
209 			if(strFieldName.Equals(NotesField)) return true;
210 
211 			return false;
212 		}
213 
GetStandardFields()214 		public static List<string> GetStandardFields()
215 		{
216 			List<string> l = new List<string>();
217 
218 			l.Add(TitleField);
219 			l.Add(UserNameField);
220 			l.Add(PasswordField);
221 			l.Add(UrlField);
222 			l.Add(NotesField);
223 
224 			return l;
225 		}
226 
227 		/// <summary>
228 		/// Check whether an entry is a TAN entry.
229 		/// </summary>
IsTanEntry(PwEntry pe)230 		public static bool IsTanEntry(PwEntry pe)
231 		{
232 			if(pe == null) { Debug.Assert(false); return false; }
233 
234 			return (pe.Strings.ReadSafe(PwDefs.TitleField) == TanTitle);
235 		}
236 
GetTranslationDisplayVersion(string strFileVersion)237 		internal static string GetTranslationDisplayVersion(string strFileVersion)
238 		{
239 			if(strFileVersion == null) { Debug.Assert(false); return string.Empty; }
240 
241 			if(strFileVersion == "2.39") return "2.39.1 / 2.39";
242 			if(strFileVersion == "2.42") return "2.42.1 / 2.42";
243 			if(strFileVersion == "2.48") return "2.48.1 / 2.48";
244 
245 			return strFileVersion;
246 		}
247 
GroupIconToEntryIcon(PwIcon i)248 		internal static PwIcon GroupIconToEntryIcon(PwIcon i)
249 		{
250 			PwIcon r = i; // Inherit by default
251 
252 			switch(i)
253 			{
254 				case PwIcon.Folder:
255 				case PwIcon.FolderOpen:
256 				case PwIcon.FolderPackage:
257 					Debug.Assert((new PwEntry(false, false)).IconId == PwIcon.Key);
258 					r = PwIcon.Key;
259 					break;
260 
261 				case PwIcon.EMailBox:
262 					r = PwIcon.EMail;
263 					break;
264 
265 				default: break;
266 			}
267 
268 			return r;
269 		}
270 	}
271 
272 	// #pragma warning disable 1591 // Missing XML comments warning
273 	/// <summary>
274 	/// Search parameters for group and entry searches.
275 	/// </summary>
276 	public sealed class SearchParameters
277 	{
278 		private string m_strName = string.Empty;
279 		[DefaultValue("")]
280 		public string Name
281 		{
282 			get { return m_strName; }
283 			set
284 			{
285 				if(value == null) throw new ArgumentNullException("value");
286 				m_strName = value;
287 			}
288 		}
289 
290 		private string m_strText = string.Empty;
291 		[DefaultValue("")]
292 		public string SearchString
293 		{
294 			get { return m_strText; }
295 			set
296 			{
297 				if(value == null) throw new ArgumentNullException("value");
298 				m_strText = value;
299 			}
300 		}
301 
302 		private PwSearchMode m_sm = PwSearchMode.Simple;
303 		public PwSearchMode SearchMode
304 		{
305 			get { return m_sm; }
306 			set { m_sm = value; }
307 		}
308 
309 		[DefaultValue(false)]
310 		[Obsolete]
311 		[XmlIgnore]
312 		public bool RegularExpression
313 		{
314 			get { return (m_sm == PwSearchMode.Regular); }
315 			set { m_sm = (value ? PwSearchMode.Regular : PwSearchMode.Simple); }
316 		}
317 
318 		private bool m_bSearchInTitles = true;
319 		[DefaultValue(true)]
320 		public bool SearchInTitles
321 		{
322 			get { return m_bSearchInTitles; }
323 			set { m_bSearchInTitles = value; }
324 		}
325 
326 		private bool m_bSearchInUserNames = true;
327 		[DefaultValue(true)]
328 		public bool SearchInUserNames
329 		{
330 			get { return m_bSearchInUserNames; }
331 			set { m_bSearchInUserNames = value; }
332 		}
333 
334 		private bool m_bSearchInPasswords = false;
335 		[DefaultValue(false)]
336 		public bool SearchInPasswords
337 		{
338 			get { return m_bSearchInPasswords; }
339 			set { m_bSearchInPasswords = value; }
340 		}
341 
342 		private bool m_bSearchInUrls = true;
343 		[DefaultValue(true)]
344 		public bool SearchInUrls
345 		{
346 			get { return m_bSearchInUrls; }
347 			set { m_bSearchInUrls = value; }
348 		}
349 
350 		private bool m_bSearchInNotes = true;
351 		[DefaultValue(true)]
352 		public bool SearchInNotes
353 		{
354 			get { return m_bSearchInNotes; }
355 			set { m_bSearchInNotes = value; }
356 		}
357 
358 		private bool m_bSearchInOther = true;
359 		[DefaultValue(true)]
360 		public bool SearchInOther
361 		{
362 			get { return m_bSearchInOther; }
363 			set { m_bSearchInOther = value; }
364 		}
365 
366 		private bool m_bSearchInStringNames = false;
367 		[DefaultValue(false)]
368 		public bool SearchInStringNames
369 		{
370 			get { return m_bSearchInStringNames; }
371 			set { m_bSearchInStringNames = value; }
372 		}
373 
374 		private bool m_bSearchInTags = true;
375 		[DefaultValue(true)]
376 		public bool SearchInTags
377 		{
378 			get { return m_bSearchInTags; }
379 			set { m_bSearchInTags = value; }
380 		}
381 
382 		private bool m_bSearchInUuids = false;
383 		[DefaultValue(false)]
384 		public bool SearchInUuids
385 		{
386 			get { return m_bSearchInUuids; }
387 			set { m_bSearchInUuids = value; }
388 		}
389 
390 		private bool m_bSearchInGroupPaths = false;
391 		[DefaultValue(false)]
392 		public bool SearchInGroupPaths
393 		{
394 			get { return m_bSearchInGroupPaths; }
395 			set { m_bSearchInGroupPaths = value; }
396 		}
397 
398 		private bool m_bSearchInGroupNames = false;
399 		[DefaultValue(false)]
400 		public bool SearchInGroupNames
401 		{
402 			get { return m_bSearchInGroupNames; }
403 			set { m_bSearchInGroupNames = value; }
404 		}
405 
406 		private bool m_bSearchInHistory = false;
407 		[DefaultValue(false)]
408 		public bool SearchInHistory
409 		{
410 			get { return m_bSearchInHistory; }
411 			set { m_bSearchInHistory = value; }
412 		}
413 
414 #if KeePassUAP
415 		private StringComparison m_scType = StringComparison.OrdinalIgnoreCase;
416 #else
417 		private StringComparison m_scType = StringComparison.InvariantCultureIgnoreCase;
418 #endif
419 		/// <summary>
420 		/// String comparison type. Specifies the condition when the specified
421 		/// text matches a group/entry string.
422 		/// </summary>
423 		public StringComparison ComparisonMode
424 		{
425 			get { return m_scType; }
426 			set { m_scType = value; }
427 		}
428 
429 		private bool m_bExcludeExpired = false;
430 		[DefaultValue(false)]
431 		public bool ExcludeExpired
432 		{
433 			get { return m_bExcludeExpired; }
434 			set { m_bExcludeExpired = value; }
435 		}
436 
437 		private bool m_bRespectEntrySearchingDisabled = true;
438 		[DefaultValue(true)]
439 		public bool RespectEntrySearchingDisabled
440 		{
441 			get { return m_bRespectEntrySearchingDisabled; }
442 			set { m_bRespectEntrySearchingDisabled = value; }
443 		}
444 
445 		private StrPwEntryDelegate m_fnDataTrf = null;
446 		[XmlIgnore]
447 		public StrPwEntryDelegate DataTransformationFn
448 		{
449 			get { return m_fnDataTrf; }
450 			set { m_fnDataTrf = value; }
451 		}
452 
453 		private string m_strDataTrf = string.Empty;
454 		/// <summary>
455 		/// Only for serialization.
456 		/// </summary>
457 		[DefaultValue("")]
458 		public string DataTransformation
459 		{
460 			get { return m_strDataTrf; }
461 			set
462 			{
463 				if(value == null) throw new ArgumentNullException("value");
464 				m_strDataTrf = value;
465 			}
466 		}
467 
468 		[XmlIgnore]
469 		public static SearchParameters None
470 		{
471 			get
472 			{
473 				SearchParameters sp = new SearchParameters();
474 
475 				Debug.Assert(sp.m_strName.Length == 0);
476 				Debug.Assert(sp.m_strText.Length == 0);
477 				Debug.Assert(sp.m_sm == PwSearchMode.Simple);
478 				sp.m_bSearchInTitles = false;
479 				sp.m_bSearchInUserNames = false;
480 				Debug.Assert(!sp.m_bSearchInPasswords);
481 				sp.m_bSearchInUrls = false;
482 				sp.m_bSearchInNotes = false;
483 				sp.m_bSearchInOther = false;
484 				Debug.Assert(!sp.m_bSearchInStringNames);
485 				sp.m_bSearchInTags = false;
486 				Debug.Assert(!sp.m_bSearchInUuids);
487 				Debug.Assert(!sp.m_bSearchInGroupPaths);
488 				Debug.Assert(!sp.m_bSearchInGroupNames);
489 				Debug.Assert(!sp.m_bSearchInHistory);
490 				// Debug.Assert(sp.m_scType == StringComparison.InvariantCultureIgnoreCase);
491 				Debug.Assert(!sp.m_bExcludeExpired);
492 				Debug.Assert(sp.m_bRespectEntrySearchingDisabled);
493 
494 				return sp;
495 			}
496 		}
497 
498 		/// <summary>
499 		/// Construct a new search parameters object.
500 		/// </summary>
SearchParameters()501 		public SearchParameters()
502 		{
503 		}
504 
Clone()505 		public SearchParameters Clone()
506 		{
507 			return (SearchParameters)this.MemberwiseClone();
508 		}
509 	}
510 	// #pragma warning restore 1591 // Missing XML comments warning
511 
512 	// #pragma warning disable 1591 // Missing XML comments warning
513 	/// <summary>
514 	/// Memory protection configuration structure (for default fields).
515 	/// </summary>
516 	public sealed class MemoryProtectionConfig : IDeepCloneable<MemoryProtectionConfig>
517 	{
518 		public bool ProtectTitle = false;
519 		public bool ProtectUserName = false;
520 		public bool ProtectPassword = true;
521 		public bool ProtectUrl = false;
522 		public bool ProtectNotes = false;
523 
524 		// public bool AutoEnableVisualHiding = false;
525 
CloneDeep()526 		public MemoryProtectionConfig CloneDeep()
527 		{
528 			return (MemoryProtectionConfig)this.MemberwiseClone();
529 		}
530 
GetProtection(string strField)531 		public bool GetProtection(string strField)
532 		{
533 			if(strField == PwDefs.TitleField) return this.ProtectTitle;
534 			if(strField == PwDefs.UserNameField) return this.ProtectUserName;
535 			if(strField == PwDefs.PasswordField) return this.ProtectPassword;
536 			if(strField == PwDefs.UrlField) return this.ProtectUrl;
537 			if(strField == PwDefs.NotesField) return this.ProtectNotes;
538 
539 			return false;
540 		}
541 	}
542 	// #pragma warning restore 1591 // Missing XML comments warning
543 
544 	public sealed class ObjectTouchedEventArgs : EventArgs
545 	{
546 		private readonly object m_o;
547 		public object Object { get { return m_o; } }
548 
549 		private readonly bool m_bModified;
550 		public bool Modified { get { return m_bModified; } }
551 
552 		private readonly bool m_bParentsTouched;
553 		public bool ParentsTouched { get { return m_bParentsTouched; } }
554 
ObjectTouchedEventArgs(object o, bool bModified, bool bParentsTouched)555 		public ObjectTouchedEventArgs(object o, bool bModified,
556 			bool bParentsTouched)
557 		{
558 			m_o = o;
559 			m_bModified = bModified;
560 			m_bParentsTouched = bParentsTouched;
561 		}
562 	}
563 
564 	public sealed class IOAccessEventArgs : EventArgs
565 	{
566 		private readonly IOConnectionInfo m_ioc;
567 		public IOConnectionInfo IOConnectionInfo { get { return m_ioc; } }
568 
569 		private readonly IOConnectionInfo m_ioc2;
570 		public IOConnectionInfo IOConnectionInfo2 { get { return m_ioc2; } }
571 
572 		private readonly IOAccessType m_t;
573 		public IOAccessType Type { get { return m_t; } }
574 
IOAccessEventArgs(IOConnectionInfo ioc, IOConnectionInfo ioc2, IOAccessType t)575 		public IOAccessEventArgs(IOConnectionInfo ioc, IOConnectionInfo ioc2,
576 			IOAccessType t)
577 		{
578 			m_ioc = ioc;
579 			m_ioc2 = ioc2;
580 			m_t = t;
581 		}
582 	}
583 
584 	public sealed class IOWebRequestEventArgs : EventArgs
585 	{
586 		private readonly WebRequest m_wr;
587 		public WebRequest Request { get { return m_wr; } }
588 
589 		private readonly IOConnectionInfo m_ioc;
590 		public IOConnectionInfo IOConnectionInfo { get { return m_ioc; } }
591 
IOWebRequestEventArgs(WebRequest r, IOConnectionInfo ioc)592 		public IOWebRequestEventArgs(WebRequest r, IOConnectionInfo ioc)
593 		{
594 			m_wr = r;
595 			m_ioc = ioc;
596 		}
597 	}
598 }
599