00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "stdafx.h"
00037 #include "DNSAnswer.h"
00038
00039 #include "ErrorHandlerMacros.h"
00040 #include "Array_ptr.h"
00041
00042 #include "SpoofBase.h"
00043
00044 #include "DNSParser.h"
00045
00046 #ifdef _MEMORY_DEBUG
00047 #define new DEBUG_NEW
00048 #define malloc DEBUG_MALLOC
00049 static char THIS_FILE[] = __FILE__;
00050 #endif
00051
00052 namespace KomodiaDNS
00053 {
00054
00055 #define CDNSAnswer_Class "CDNSAnswer"
00056
00057 CDNSAnswer::CDNSAnswer() : CErrorHandler(),
00058 m_aAnswerType(dhNone),
00059 m_usMXPriority(0),
00060 m_pSOA(NULL)
00061 {
00062 try
00063 {
00064
00065 SetName(CDNSAnswer_Class);
00066 }
00067 ERROR_HANDLER("CDNSAnswer")
00068 }
00069
00070 CDNSAnswer::CDNSAnswer(const CDNSAnswer& rAnswer) : CErrorHandler(rAnswer),
00071 m_aAnswerType(rAnswer.m_aAnswerType),
00072 m_usMXPriority(rAnswer.m_usMXPriority),
00073 m_pSOA(NULL),
00074 m_aAnswer(rAnswer.m_aAnswer)
00075 {
00076 try
00077 {
00078
00079 SetName(CDNSAnswer_Class);
00080
00081
00082 if (rAnswer.m_pSOA)
00083
00084 m_pSOA=new DNSSOARecord(*rAnswer.m_pSOA);
00085 }
00086 ERROR_HANDLER("CDNSAnswer")
00087 }
00088
00089 CDNSAnswer::~CDNSAnswer()
00090 {
00091 try
00092 {
00093
00094 DeleteBuffer();
00095 }
00096 ERROR_HANDLER("~CDNSAnswer")
00097 }
00098
00099 CDNSAnswer& CDNSAnswer::operator=(const CDNSAnswer& rAnswer)
00100 {
00101
00102 if (this==&rAnswer)
00103 return *this;
00104
00105
00106 m_aAnswerType=rAnswer.m_aAnswerType;
00107 m_aAnswer=rAnswer.m_aAnswer;
00108 m_usMXPriority=rAnswer.m_usMXPriority;
00109 m_aAnswer=rAnswer.m_aAnswer;
00110
00111
00112 delete m_pSOA;
00113
00114
00115 if (rAnswer.m_pSOA)
00116 m_pSOA=new DNSSOARecord(*rAnswer.m_pSOA);
00117 else
00118 m_pSOA=NULL;
00119
00120
00121 return *this;
00122 }
00123
00124 const DnsRRHeader& CDNSAnswer::GetAnswerStruct()const
00125 {
00126 return m_aAnswer;
00127 }
00128
00129 int CDNSAnswer::ParseBuffer(const char* pBuffer,
00130 const char* pOriginalBuffer)
00131 {
00132 try
00133 {
00134
00135
00136 const char* pBackupBuffer=pBuffer;
00137
00138
00139 unsigned short usLength;
00140 m_aAnswer.sName=CDNSParser::ParseName(pBuffer,
00141 pOriginalBuffer,
00142 usLength);
00143
00144 if (!usLength)
00145 {
00146
00147 ReportError("ParseBuffer","Received zero length!");
00148
00149
00150 return 0;
00151 }
00152
00153
00154 pBackupBuffer+=usLength;
00155
00156
00157 memcpy(&m_aAnswer.usType,
00158 pBackupBuffer,
00159 sizeof(m_aAnswer.usType));
00160 m_aAnswer.usType=htons(m_aAnswer.usType);
00161 pBackupBuffer+=sizeof(m_aAnswer.usType);
00162
00163
00164 memcpy(&m_aAnswer.usClass,
00165 pBackupBuffer,
00166 sizeof(m_aAnswer.usClass));
00167 m_aAnswer.usClass=htons(m_aAnswer.usClass);
00168 pBackupBuffer+=sizeof(m_aAnswer.usClass);
00169
00170
00171 memcpy(&m_aAnswer.ulTTL,
00172 pBackupBuffer,
00173 sizeof(m_aAnswer.ulTTL));
00174 m_aAnswer.ulTTL=htonl(m_aAnswer.ulTTL);
00175 pBackupBuffer+=sizeof(m_aAnswer.ulTTL);
00176
00177
00178 memcpy(&m_aAnswer.usRdlLength,
00179 pBackupBuffer,
00180 sizeof(m_aAnswer.usRdlLength));
00181 m_aAnswer.usRdlLength=htons(m_aAnswer.usRdlLength);
00182 pBackupBuffer+=sizeof(m_aAnswer.usRdlLength);
00183
00184
00185 BOOL bError;
00186 bError=FALSE;
00187
00188
00189 std::string sParsedName;
00190
00191
00192 if (m_aAnswer.usType==CDNSQuery::CNAME ||
00193 m_aAnswer.usType==CDNSQuery::NS ||
00194 m_aAnswer.usType==CDNSQuery::PTR)
00195 {
00196
00197 sParsedName=CDNSParser::ParseName(pBackupBuffer,
00198 pOriginalBuffer,
00199 usLength);
00200
00201
00202 if (!usLength)
00203 {
00204
00205 ReportError("ParseBuffer","Failed to parsed canonical name!");
00206
00207
00208 bError=TRUE;
00209 }
00210
00211
00212 usLength=m_aAnswer.usRdlLength;
00213 }
00214 else if (m_aAnswer.usType==CDNSQuery::A)
00215 {
00216
00217 usLength=m_aAnswer.usRdlLength;
00218
00219
00220 if (m_aAnswer.usRdlLength>4)
00221 {
00222
00223 ReportError("ParseBuffer","Unexpected A length!",m_aAnswer.usRdlLength);
00224
00225
00226 bError=TRUE;
00227 }
00228 else
00229 {
00230
00231 long lIP;
00232 lIP=*((long*)pBackupBuffer);
00233
00234
00235 char aTmp[11];
00236 sprintf(aTmp,"%lu",lIP);
00237
00238
00239 sParsedName=aTmp;
00240 }
00241 }
00242 else if (m_aAnswer.usType==CDNSQuery::MX)
00243 {
00244
00245 memcpy(&m_usMXPriority,
00246 pBackupBuffer,
00247 sizeof(m_usMXPriority));
00248
00249
00250 m_usMXPriority=htons(m_usMXPriority);
00251
00252
00253
00254 sParsedName=CDNSParser::ParseName(pBackupBuffer+sizeof(m_usMXPriority),
00255 pOriginalBuffer,
00256 usLength);
00257
00258
00259 if (!usLength)
00260 {
00261
00262 ReportError("ParseBuffer","Failed to parsed MX name!");
00263
00264
00265 bError=TRUE;
00266 }
00267
00268
00269 usLength=m_aAnswer.usRdlLength;
00270 }
00271 else if (m_aAnswer.usType==CDNSQuery::SOA)
00272 {
00273
00274 m_pSOA=ParseSOA(m_aAnswer.usRdlLength,
00275 pBackupBuffer,
00276 pOriginalBuffer);
00277
00278
00279 usLength=m_aAnswer.usRdlLength;
00280 }
00281 else
00282 {
00283
00284 ReportError("ParseBuffer","Not supported address type!");
00285
00286
00287 return 0;
00288 }
00289
00290
00291 if (bError)
00292 ReportError("ParseBuffer","Received zero length, trying to recover!");
00293
00294
00295 pBackupBuffer+=usLength;
00296
00297
00298 m_aAnswer.sData=sParsedName;
00299
00300
00301 return pBackupBuffer-pBuffer;
00302 }
00303 ERROR_HANDLER_RETURN("ParseBuffer",0)
00304 }
00305
00306 void CDNSAnswer::DeleteBuffer()
00307 {
00308 try
00309 {
00310
00311 delete m_pSOA;
00312 m_pSOA=NULL;
00313 }
00314 ERROR_HANDLER("DeleteBuffer")
00315 }
00316
00317 void CDNSAnswer::SetAnswerType(DnsHeaderType aType)
00318 {
00319 m_aAnswerType=aType;
00320 }
00321
00322 CDNSAnswer::DnsHeaderType CDNSAnswer::GetAnswerType()const
00323 {
00324 return m_aAnswerType;
00325 }
00326
00327 CDNSQuery::DNSQueryTypes CDNSAnswer::GetResourceType()const
00328 {
00329 return (CDNSQuery::DNSQueryTypes)m_aAnswer.usType;
00330 }
00331
00332 DNSSOARecord* CDNSAnswer::ParseSOA(unsigned short usSOASize,
00333 const char* pBuffer,
00334 const char* pOriginalBuffer)
00335 {
00336 try
00337 {
00338
00339 const char* pBackupBuffer=pBuffer;
00340
00341
00342 DNSSOARecord* pRecord;
00343 pRecord=new DNSSOARecord;
00344
00345
00346 std::auto_ptr<DNSSOARecord> pProtection(pRecord);
00347
00348
00349 unsigned short usLength;
00350 pRecord->sPrimaryNameServer=CDNSParser::ParseName(pBuffer,
00351 pOriginalBuffer,
00352 usLength);
00353
00354 if (!usLength)
00355 {
00356
00357 ReportError("ParseSOA","Failed to parse primary name server!");
00358
00359
00360 return NULL;
00361 }
00362
00363
00364 pBuffer+=usLength;
00365
00366
00367 pRecord->sAuthorativeMailbox=CDNSParser::ParseName(pBuffer,
00368 pOriginalBuffer,
00369 usLength);
00370
00371
00372 if (!usLength)
00373 {
00374
00375 ReportError("ParseSOA","Failed to parse authorative mailbox!");
00376
00377
00378 return NULL;
00379 }
00380
00381
00382 pBackupBuffer+=usSOASize-DNSSOARecordCopySize;
00383
00384
00385 memcpy(&pRecord->ulVersionNumber,
00386 pBackupBuffer,
00387 DNSSOARecordCopySize);
00388
00389
00390 pRecord->ulVersionNumber=htonl(pRecord->ulVersionNumber);
00391 pRecord->ulRefreshInterval=htonl(pRecord->ulRefreshInterval);
00392 pRecord->ulRetryInterval=htonl(pRecord->ulRetryInterval);
00393 pRecord->ulExpirationLimit=htonl(pRecord->ulExpirationLimit);
00394 pRecord->ulMinimumTTL=htonl(pRecord->ulMinimumTTL);
00395
00396
00397 pProtection.release();
00398
00399
00400 return pRecord;
00401 }
00402 ERROR_HANDLER_RETURN("ParseSOA",NULL)
00403 }
00404
00405 unsigned short CDNSAnswer::GetMXPriority()const
00406 {
00407 return m_usMXPriority;
00408 }
00409
00410 const DNSSOARecord* CDNSAnswer::GetSOARecord()const
00411 {
00412 return m_pSOA;
00413 }
00414
00415 const std::string& CDNSAnswer::GetData()const
00416 {
00417 return m_aAnswer.sData;
00418 }
00419
00420 const std::string& CDNSAnswer::GetName()const
00421 {
00422 return m_aAnswer.sName;
00423 }
00424
00425 std::string CDNSAnswer::GetAnswerParsed(BOOL bWindowsLines,
00426 BOOL bBrief)const
00427 {
00428 try
00429 {
00430
00431
00432 char aEndOfLine[3];
00433
00434
00435 if (bWindowsLines)
00436 {
00437 aEndOfLine[0]=13;
00438 aEndOfLine[1]=10;
00439 aEndOfLine[2]=0;
00440 }
00441 else
00442 {
00443 aEndOfLine[0]='\n';
00444 aEndOfLine[1]=0;
00445 }
00446
00447
00448 std::string sAnswer;
00449
00450
00451
00452 if (m_aAnswer.usType==CDNSQuery::SOA)
00453 {
00454
00455 sAnswer+=m_aAnswer.sName;
00456 sAnswer+=aEndOfLine;
00457
00458
00459 sAnswer+=GetSOARecord(std::string(" "),
00460 aEndOfLine);
00461 }
00462 if (m_aAnswer.usType==CDNSQuery::A)
00463 {
00464
00465
00466 if (m_aAnswerType==dhAnswer)
00467 {
00468
00469 sAnswer+="Name: ";
00470 sAnswer+=m_aAnswer.sName;
00471 sAnswer+=aEndOfLine;
00472
00473
00474 sAnswer+="Address: ";
00475 }
00476 else if (m_aAnswerType==dhAdditional)
00477 {
00478
00479 sAnswer+=m_aAnswer.sName;
00480 sAnswer+=' ';
00481
00482
00483 sAnswer+="internet address = ";
00484 }
00485
00486
00487 sAnswer+=CSpoofBase::LongToStdString(atol(m_aAnswer.sData.c_str()));
00488 }
00489 else if (m_aAnswer.usType==CDNSQuery::MX)
00490 {
00491
00492 sAnswer+=m_aAnswer.sName;
00493 sAnswer+=' ';
00494
00495
00496 char aTmp[11];
00497 itoa(m_usMXPriority,aTmp,10);
00498
00499
00500 sAnswer+="MX preference = ";
00501 sAnswer+=aTmp;
00502 sAnswer+=std::string(", ");
00503
00504
00505 sAnswer+="mail exchanger = ";
00506 sAnswer+=m_aAnswer.sData;
00507 }
00508 else if (m_aAnswer.usType==CDNSQuery::NS)
00509 {
00510
00511 sAnswer+=m_aAnswer.sName;
00512 sAnswer+=' ';
00513
00514
00515 sAnswer+="nameserver = ";
00516 sAnswer+=m_aAnswer.sData;
00517 }
00518 else if (m_aAnswer.usType==CDNSQuery::PTR)
00519 {
00520
00521 sAnswer+=m_aAnswer.sName;
00522 sAnswer+=' ';
00523
00524
00525 sAnswer+="name = ";
00526 sAnswer+=m_aAnswer.sData;
00527 }
00528
00529
00530 return sAnswer;
00531 }
00532 ERROR_HANDLER_RETURN("GetAnswerParsed","")
00533 }
00534
00535 std::string CDNSAnswer::GetSOARecord(const std::string& rShift,
00536 const std::string& rTerminator)const
00537 {
00538 try
00539 {
00540
00541 std::string sSOA;
00542
00543
00544
00545 sSOA+=rShift;
00546 sSOA+="primary name server = ";
00547 sSOA+=m_pSOA->sPrimaryNameServer;
00548 sSOA+=rTerminator;
00549
00550
00551 sSOA+=rShift;
00552 sSOA+="responsible mail addr = ";
00553 sSOA+=m_pSOA->sAuthorativeMailbox;
00554 sSOA+=rTerminator;
00555
00556
00557 sSOA+=rShift;
00558 sSOA+="serial = ";
00559 sSOA+=ConvertUL(m_pSOA->ulVersionNumber);
00560 sSOA+=rTerminator;
00561
00562
00563 sSOA+=rShift;
00564 sSOA+="refresh = ";
00565 sSOA+=ConvertUL(m_pSOA->ulRefreshInterval);
00566 sSOA+=ConvertMS(m_pSOA->ulRefreshInterval);
00567 sSOA+=rTerminator;
00568
00569
00570 sSOA+=rShift;
00571 sSOA+="retry = ";
00572 sSOA+=ConvertUL(m_pSOA->ulRetryInterval);
00573 sSOA+=ConvertMS(m_pSOA->ulRetryInterval);
00574 sSOA+=rTerminator;
00575
00576
00577 sSOA+=rShift;
00578 sSOA+="expire = ";
00579 sSOA+=ConvertUL(m_pSOA->ulExpirationLimit);
00580 sSOA+=ConvertMS(m_pSOA->ulExpirationLimit);
00581 sSOA+=rTerminator;
00582
00583
00584 sSOA+=rShift;
00585 sSOA+="default TTL = ";
00586 sSOA+=ConvertUL(m_pSOA->ulMinimumTTL);
00587 sSOA+=ConvertMS(m_pSOA->ulMinimumTTL);
00588 sSOA+=rTerminator;
00589
00590
00591 return sSOA;
00592 }
00593 ERROR_HANDLER_RETURN("GetSOARecord","")
00594 }
00595
00596 std::string CDNSAnswer::ConvertUL(unsigned long ulNumber)
00597 {
00598
00599 char aTmp[11];
00600 sprintf(aTmp,"%lu",ulNumber);
00601
00602
00603 return aTmp;
00604 }
00605
00606 std::string CDNSAnswer::ConvertMS(unsigned long ulNumber)
00607 {
00608
00609 char aTmp[100];
00610
00611
00612 if (ulNumber<60)
00613 sprintf(aTmp," (%lu seconds)",ulNumber);
00614 else if (ulNumber<3600)
00615 sprintf(aTmp," (%lu minutes)",ulNumber/60);
00616 else if (ulNumber<86400)
00617 sprintf(aTmp," (%lu hours)",ulNumber/3600);
00618 else
00619 sprintf(aTmp," (%lu days)",ulNumber/86400);
00620
00621
00622 return aTmp;
00623 }
00624
00625
00626 }