예제 #1
0
		/// <summary>
		/// Digitally sign the message using a DomainKeys Identified Mail (DKIM) signature.
		/// </summary>
		/// <remarks>
		/// Digitally signs the message using a DomainKeys Identified Mail (DKIM) signature.
		/// </remarks>
		/// <param name="signer">The DKIM signer.</param>
		/// <param name="headers">The headers to sign.</param>
		/// <param name="headerCanonicalizationAlgorithm">The header canonicalization algorithm.</param>
		/// <param name="bodyCanonicalizationAlgorithm">The body canonicalization algorithm.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="headers"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="headers"/> does not contain the 'From' header.</para>
		/// <para>-or-</para>
		/// <para><paramref name="headers"/> contains one or more of the following headers: Return-Path,
		/// Received, Comments, Keywords, Bcc, Resent-Bcc, or DKIM-Signature.</para>
		/// </exception>
		public void Sign (DkimSigner signer, IList<HeaderId> headers, DkimCanonicalizationAlgorithm headerCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple, DkimCanonicalizationAlgorithm bodyCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple)
		{
			Sign (FormatOptions.Default, signer, headers, headerCanonicalizationAlgorithm, bodyCanonicalizationAlgorithm);
		}
예제 #2
0
        public void UpdateSettings(Settings config)
        {
            lock (settingsMutex)
            {
                // Load the list of domains
                domains.Clear();

                DkimSignatureAlgorithm signatureAlgorithm;

                switch (config.SigningAlgorithm)
                {
                case DkimAlgorithmKind.RsaSha1:
                    signatureAlgorithm = DkimSignatureAlgorithm.RsaSha1;
                    break;

                case DkimAlgorithmKind.RsaSha256:
                    signatureAlgorithm = DkimSignatureAlgorithm.RsaSha256;
                    break;

                default:
                    // ReSharper disable once NotResolvedInText
                    throw new ArgumentOutOfRangeException("config.SigningAlgorithm");
                }


                foreach (DomainElement domainElement in config.Domains)
                {
                    string privateKey = domainElement.PrivateKeyPathAbsolute(
                        Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
                    if (String.IsNullOrEmpty(privateKey) || !File.Exists(privateKey))
                    {
                        Logger.LogError("The private key for domain " + domainElement.Domain + " wasn't found: " + privateKey + ". Ignoring domain.");
                    }

                    //check if the private key can be parsed
                    try
                    {
                        KeyHelper.ParseKeyPair(privateKey);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError("Couldn't load private key for domain " + domainElement.Domain + ": " + ex.Message);
                        continue;
                    }

                    MimeKit.Cryptography.DkimSigner signer;
                    try
                    {
                        AsymmetricKeyParameter key = KeyHelper.ParsePrivateKey(privateKey);
                        signer = new MimeKit.Cryptography.DkimSigner(key, domainElement.Domain,
                                                                     domainElement.Selector)
                        {
                            SignatureAlgorithm = signatureAlgorithm
                        };
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError("Could not initialize MimeKit DkimSigner for domain " + domainElement.Domain + ": " + ex.Message);
                        continue;
                    }
                    domains.Add(domainElement.Domain, new DomainElementSigner(domainElement, signer));
                }

                headerCanonicalization = config.HeaderCanonicalization == DkimCanonicalizationKind.Relaxed ? DkimCanonicalizationAlgorithm.Relaxed : DkimCanonicalizationAlgorithm.Simple;

                bodyCanonicalization = config.BodyCanonicalization == DkimCanonicalizationKind.Relaxed ? DkimCanonicalizationAlgorithm.Relaxed : DkimCanonicalizationAlgorithm.Simple;

                List <HeaderId> headerList = new List <HeaderId>();
                foreach (string headerToSign in config.HeadersToSign)
                {
                    HeaderId headerId;
#if EX_2007_SP3 || EX_2010 || EX_2010_SP1 || EX_2010_SP2 || EX_2010_SP3
                    if (!TryParseHeader(headerToSign, out headerId) || (headerId == HeaderId.Unknown))
#else
                    if (!Enum.TryParse(headerToSign, true, out headerId) || (headerId == HeaderId.Unknown))
#endif
                    {
                        Logger.LogWarning("Invalid value for header to sign: '" + headerToSign + "'. This header will be ignored.");
                    }
                    headerList.Add(headerId);
                }

                // The From header must always be signed according to the DKIM specification.
                if (!headerList.Contains(HeaderId.From))
                {
                    headerList.Add(HeaderId.From);
                }
                eligibleHeaders = headerList.ToArray();
            }
        }
예제 #3
0
		/// <summary>
		/// Digitally sign the message using a DomainKeys Identified Mail (DKIM) signature.
		/// </summary>
		/// <remarks>
		/// Digitally signs the message using a DomainKeys Identified Mail (DKIM) signature.
		/// </remarks>
		/// <param name="options">The formatting options.</param>
		/// <param name="signer">The DKIM signer.</param>
		/// <param name="headers">The list of header fields to sign.</param>
		/// <param name="headerCanonicalizationAlgorithm">The header canonicalization algorithm.</param>
		/// <param name="bodyCanonicalizationAlgorithm">The body canonicalization algorithm.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="options"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signer"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="headers"/> is <c>null</c>.</para>
		/// </exception>
		/// <exception cref="System.ArgumentException">
		/// <para><paramref name="headers"/> does not contain the 'From' header.</para>
		/// <para>-or-</para>
		/// <para><paramref name="headers"/> contains one or more of the following headers: Return-Path,
		/// Received, Comments, Keywords, Bcc, Resent-Bcc, or DKIM-Signature.</para>
		/// </exception>
		void Sign (FormatOptions options, DkimSigner signer, IList<HeaderId> headers, DkimCanonicalizationAlgorithm headerCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple, DkimCanonicalizationAlgorithm bodyCanonicalizationAlgorithm = DkimCanonicalizationAlgorithm.Simple)
		{
			if (options == null)
				throw new ArgumentNullException ("options");

			if (signer == null)
				throw new ArgumentNullException ("signer");

			if (headers == null)
				throw new ArgumentNullException ("headers");

			if (!headers.Contains (HeaderId.From))
				throw new ArgumentException ("The list of headers to sign MUST include the 'From' header.");

			var fields = new string[headers.Count];
			for (int i = 0; i < headers.Count; i++) {
				if (DkimShouldNotInclude.Contains (headers[i]))
					throw new ArgumentException (string.Format ("The list of headers to sign SHOULD NOT include the '{0}' header.", headers[i].ToHeaderName ()));

				fields[i] = headers[i].ToHeaderName ().ToLowerInvariant ();
			}

			if (version == null && Body != null && Body.Headers.Count > 0)
				MimeVersion = new Version (1, 0);

			Prepare (EncodingConstraint.SevenBit, 78);

			var t = DateTime.Now - DateUtils.UnixEpoch;
			var value = new StringBuilder ("v=1");
			byte[] signature, hash;
			Header dkim;

			options = options.Clone ();
			options.NewLineFormat = NewLineFormat.Dos;

			switch (signer.SignatureAlgorithm) {
			case DkimSignatureAlgorithm.RsaSha256:
				value.Append ("; a=rsa-sha256");
				break;
			default:
				value.Append ("; a=rsa-sha1");
				break;
			}

			value.AppendFormat ("; d={0}; s={1}", signer.Domain, signer.Selector);
			value.AppendFormat ("; c={0}/{1}",
				headerCanonicalizationAlgorithm.ToString ().ToLowerInvariant (),
				bodyCanonicalizationAlgorithm.ToString ().ToLowerInvariant ());
			if (!string.IsNullOrEmpty (signer.QueryMethod))
				value.AppendFormat ("; q={0}", signer.QueryMethod);
			if (!string.IsNullOrEmpty (signer.AgentOrUserIdentifier))
				value.AppendFormat ("; i={0}", signer.AgentOrUserIdentifier);
			value.AppendFormat ("; t={0}", (long) t.TotalSeconds);

			using (var stream = new DkimSignatureStream (DkimGetDigestSigner (signer.SignatureAlgorithm, signer.PrivateKey))) {
				using (var filtered = new FilteredStream (stream)) {
					filtered.Add (options.CreateNewLineFilter ());

					// write the specified message headers
					DkimWriteHeaders (options, fields, headerCanonicalizationAlgorithm, filtered);

					value.AppendFormat ("; h={0}", string.Join (":", fields.ToArray ()));

					hash = DkimHashBody (options, signer.SignatureAlgorithm, bodyCanonicalizationAlgorithm, -1);
					value.AppendFormat ("; bh={0}", Convert.ToBase64String (hash));
					value.Append ("; b=");

					dkim = new Header (HeaderId.DkimSignature, value.ToString ());
					Headers.Insert (0, dkim);

					switch (headerCanonicalizationAlgorithm) {
					case DkimCanonicalizationAlgorithm.Relaxed:
						DkimWriteHeaderRelaxed (options, filtered, dkim);
						break;
					default:
						DkimWriteHeaderSimple (options, filtered, dkim);
						break;
					}

					filtered.Flush ();
				}

				signature = stream.GenerateSignature ();

				dkim.Value += Convert.ToBase64String (signature);
			}
		}
예제 #4
0
        public void UpdateSettings(Settings config)
        {
            lock (settingsMutex)
            {
                // Load the list of domains
                domains.Clear();

                DkimSignatureAlgorithm signatureAlgorithm;
                
                switch (config.SigningAlgorithm)
                {
                    case DkimAlgorithmKind.RsaSha1:
                        signatureAlgorithm = DkimSignatureAlgorithm.RsaSha1;
                        break;
                    case DkimAlgorithmKind.RsaSha256:
                        signatureAlgorithm = DkimSignatureAlgorithm.RsaSha256;
                        break;
                    default:
                        // ReSharper disable once NotResolvedInText
                        throw new ArgumentOutOfRangeException("config.SigningAlgorithm");
                }


                foreach (DomainElement domainElement in config.Domains)
                {
                    string privateKey = domainElement.PrivateKeyPathAbsolute(
                        Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
                    if (String.IsNullOrEmpty(privateKey) || !File.Exists(privateKey))
                    {
                        Logger.LogError("The private key for domain " + domainElement.Domain + " wasn't found: " + privateKey + ". Ignoring domain.");

                    }
                    
                    //check if the private key can be parsed
                    try
                    {
                        KeyHelper.ParseKeyPair(privateKey);
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError("Couldn't load private key for domain " + domainElement.Domain + ": " + ex.Message);
                        continue;
                    }

                    MimeKit.Cryptography.DkimSigner signer;
                    try
                    {
                        AsymmetricKeyParameter key = KeyHelper.ParsePrivateKey(privateKey);
                        signer = new MimeKit.Cryptography.DkimSigner(key, domainElement.Domain,
                            domainElement.Selector)
                        {
                            SignatureAlgorithm = signatureAlgorithm
                        };
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError("Could not initialize MimeKit DkimSigner for domain " + domainElement.Domain + ": " + ex.Message);
                        continue;
                    }
                    domains.Add(domainElement.Domain, new DomainElementSigner(domainElement, signer));
                }

                headerCanonicalization = config.HeaderCanonicalization == DkimCanonicalizationKind.Relaxed ? DkimCanonicalizationAlgorithm.Relaxed : DkimCanonicalizationAlgorithm.Simple;
                
                bodyCanonicalization = config.BodyCanonicalization == DkimCanonicalizationKind.Relaxed ? DkimCanonicalizationAlgorithm.Relaxed : DkimCanonicalizationAlgorithm.Simple;

                List<HeaderId> headerList = new List<HeaderId>();
                foreach (string headerToSign in config.HeadersToSign)
                {
                    HeaderId headerId;
#if EX_2007_SP3 || EX_2010 || EX_2010_SP1 || EX_2010_SP2 || EX_2010_SP3
                    if (!TryParseHeader(headerToSign, out headerId))
#else
                    if (!Enum.TryParse(headerToSign, true, out headerId))
#endif
                    {
                        Logger.LogWarning("Invalid value for header to sign: '" + headerToSign + "'. This header will be ignored.");
                    }
                    headerList.Add(headerId);
                }

                // The From header must always be signed according to the 
                // DKIM specification.
                if (!headerList.Contains(HeaderId.From))
                {
                    headerList.Add(HeaderId.From);
                }
                eligibleHeaders = headerList.ToArray();
            }
        }