예제 #1
0
 private static Int16 toSetAppropriateEndianess(Int16 value)
 {
     return(Endianess.MachineArchIsLittleEndian ? Endianess.toBigEndian(value) : value);
 }
예제 #2
0
            public bool AskDNS(string domain, string email)
            {
                var transactionID = (Int16)(new Random().Next(maxValue: Int16.MaxValue));

                var header = new DNSHeader
                {
                    transactionID           = transactionID,
                    flags                   = 0x0100, // Just a standard query
                    questionResourceCount   = 1,      // We have one question
                    answerResourceCount     = 0,
                    authorityResourceCount  = 0,
                    additionalResourceCount = 0
                };

                var question = new DNSQuestion(domain,
                                               DNSQuestion.Types.MailExchangeRecord);   // We want to know about mail server

                var    sizeDNSQuery = header.SizeOf() + question.SizeOf();
                var    arrDNSQuery  = new byte[sizeDNSQuery];
                IntPtr ptrHeader    = Marshal.AllocHGlobal(header.SizeOf());

                Marshal.StructureToPtr(header, ptrHeader, true);
                Marshal.Copy(ptrHeader, arrDNSQuery, 0, header.SizeOf());
                Marshal.FreeHGlobal(ptrHeader);

                // Copy char data, no need to worry about endianess for char
                question.name.CopyTo(arrDNSQuery, header.SizeOf());

                var arrQuestionType      = BitConverter.GetBytes(Endianess.toBigEndian(question.type));
                var arrQuestionClassType = BitConverter.GetBytes(Endianess.toBigEndian(question.classType));

                arrQuestionType.CopyTo(arrDNSQuery, header.SizeOf() + question.name.Length * sizeof(byte));
                arrQuestionClassType.CopyTo(arrDNSQuery, header.SizeOf() + question.name.Length * sizeof(byte) + arrQuestionType.Length);

                // Send datagram
                _dNSClient.Send(arrDNSQuery, arrDNSQuery.Length * sizeof(byte));

                // Get response
                do
                {
                    var result = _dNSClient.ReceiveAsync().Result;

                    // Make sure it is from correct domain
                    if (result.RemoteEndPoint.Address.Equals(_dNSServer))
                    {
                        // Make sure packet has valid size header
                        if (result.Buffer.Length > header.SizeOf())
                        {
                            // Convert to DNSHeader
                            ptrHeader = Marshal.AllocHGlobal(header.SizeOf());
                            Marshal.Copy(result.Buffer, 0, ptrHeader, header.SizeOf());
                            header = (DNSHeader)Marshal.PtrToStructure(ptrHeader, header.GetType());
                            Marshal.FreeHGlobal(ptrHeader);

                            // Check that this is the correct transaction packet response
                            if (header.transactionID == transactionID)
                            {
                                // Check that flags has no error and there is atleast one answer
                                if (((header.flags & 0xf) != 0) || header.answerResourceCount == 0)
                                {
                                    return(false);
                                }

                                // List of mail servers and their preferences
                                List <Tuple <int, string> > listMailServerAndPrefs = new List <Tuple <int, string> >();

                                // Determine the start index of Answers structure
                                int indexStartOfAnswer = arrDNSQuery.Length;

                                for (int i = 0; i < header.answerResourceCount; ++i)
                                {
                                    if ((result.Buffer[indexStartOfAnswer] & 0xC0) == 0)
                                    {
                                        throw new NotImplementedException("DNS answer name must be an offset");
                                    }

                                    // Convert from byte stream to answer structure
                                    IntPtr ptrAnswer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DNSResource)));
                                    Marshal.Copy(result.Buffer, indexStartOfAnswer, ptrAnswer, Marshal.SizeOf(typeof(DNSResource)));
                                    var answer = (DNSResource)Marshal.PtrToStructure(ptrAnswer, typeof(DNSResource));
                                    Marshal.FreeHGlobal(ptrAnswer);

                                    // Increment index ahead
                                    indexStartOfAnswer += answer.SizeOf();
                                    if (indexStartOfAnswer > result.Buffer.Length)
                                    {
                                        break;
                                    }

                                    // Read preference no, smaller number is more preferred server
                                    if (answer.dataLength < 2)
                                    {
                                        continue;
                                    }

                                    Int16 preferenceMailExchangeServer = BitConverter.ToInt16(result.Buffer, indexStartOfAnswer);
                                    if (Endianess.MachineArchIsLittleEndian)
                                    {
                                        preferenceMailExchangeServer = Endianess.toLittleEndian(preferenceMailExchangeServer);
                                    }
                                    indexStartOfAnswer += Marshal.SizeOf(preferenceMailExchangeServer);

                                    // Read server name
                                    int sizeServerName = answer.dataLength - Marshal.SizeOf(preferenceMailExchangeServer);
                                    if (sizeServerName < 2)
                                    {
                                        continue;
                                    }

                                    if (indexStartOfAnswer + sizeServerName > result.Buffer.Length)
                                    {
                                        break;
                                    }

                                    string serverName = string.Empty;
                                    int    j          = indexStartOfAnswer;
                                    while (j < indexStartOfAnswer + sizeServerName - 1)
                                    {
                                        if ((result.Buffer[j] & 0xC0) != 0)
                                        {
                                            // It's an offset
                                            var offset = BitConverter.ToInt16(result.Buffer, j);
                                            if (Endianess.MachineArchIsLittleEndian)
                                            {
                                                offset = Endianess.toLittleEndian(offset);
                                            }
                                            offset &= 0x3F; // Remove two most significant bits
                                            j      += Marshal.SizeOf(offset);

                                            // Transverse position from offset until null
                                            do
                                            {
                                                serverName += Encoding.ASCII.GetString(result.Buffer, offset + 1, result.Buffer[offset]) + '.';
                                                offset     += (Int16)(result.Buffer[offset] + 1);
                                            } while (result.Buffer[offset] != 0);
                                        }
                                        else
                                        {
                                            // It's just size
                                            serverName += System.Text.Encoding.ASCII.GetString(result.Buffer, j + 1, result.Buffer[j]) + '.';
                                            j          += result.Buffer[j] + 1;
                                        }
                                    }

                                    indexStartOfAnswer += answer.dataLength - Marshal.SizeOf(preferenceMailExchangeServer);

                                    if (string.IsNullOrEmpty(serverName) && serverName.Length > 2)
                                    {
                                        continue;
                                    }

                                    serverName = serverName.Substring(0, serverName.Length - 1);    // Remove terminating dot

                                    listMailServerAndPrefs.Add(new Tuple <int, string>((int)preferenceMailExchangeServer, serverName));
                                }

                                // Sort by preference
                                listMailServerAndPrefs = listMailServerAndPrefs.OrderBy(x => x.Item1).ToList();

                                // Connect with SMTP
                                _sMTPClient = new TcpClient();
                                _sMTPClient.ConnectAsync(listMailServerAndPrefs.First().Item2, _sMTPPort).Wait();
                                if (!_sMTPClient.Connected)
                                {
                                    throw new WebException("SMTP server refused connection");
                                }

                                var arrSMTPResponse  = new byte[256];
                                var sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse);
                                var connectResponse  = Encoding.ASCII.GetString(arrSMTPResponse);
                                if (!connectResponse.StartsWith("220"))
                                {
                                    throw new WebException("SMTP server refused to connect");
                                }

                                _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("HELO " + HelloServer + "\r\n"));
                                sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse);
                                var heloResponse = Encoding.ASCII.GetString(arrSMTPResponse);
                                if (!heloResponse.StartsWith("250"))
                                {
                                    throw new WebException("SMTP server refused to handshake");
                                }

                                _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("MAIL FROM:<" + QueryEmail + ">\r\n"));
                                sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse);
                                var mailfromResponse = Encoding.ASCII.GetString(arrSMTPResponse);
                                if (!mailfromResponse.StartsWith("250"))
                                {
                                    throw new WebException("SMTP server refused to accept mail from");
                                }

                                _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("RCPT TO:<" + email + ">\r\n"));
                                sizeSMTPResponse = _sMTPClient.Client.Receive(arrSMTPResponse);
                                var rcpttoResponse = Encoding.ASCII.GetString(arrSMTPResponse);

                                _sMTPClient.Client.Send(Encoding.ASCII.GetBytes("QUIT"));   // Bye

                                _sMTPClient.Close();

                                if (!rcpttoResponse.StartsWith("250"))
                                {
                                    return(false);
                                }

                                break;
                            }
                        }
                    }
                } while (true);

                return(true);
            }