2
0

dllmain.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //Set includes
  2. #include <iostream>
  3. #include <fstream>
  4. #include <Windows.h>
  5. #include <Authif.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <ctime>
  9. #include <string>
  10. #include "WinHttpClient.h"
  11. #include <rapidjson\document.h>
  12. #include "stdafx.h"
  13. //#define _CRT_SECURE_NO_WARNINGS
  14. void logger(const char * msg) //Logger function ==> Write to a log file
  15. {
  16. FILE * fp = fopen("C:/Temp/NPS.log.txt", "a");
  17. if (fp)
  18. {
  19. fprintf(fp, "%s\n", msg);
  20. fclose(fp);
  21. }
  22. }
  23. DWORD WINAPI RadiusExtensionProcess2(
  24. _Inout_ PRADIUS_EXTENSION_CONTROL_BLOCK pECB //The famous function
  25. )
  26. {
  27. if (pECB != NULL) //Check if we got some data from NPS
  28. {
  29. if (pECB->rcRequestType == rcAccessRequest) //Check if the request is a access request
  30. {
  31. RADIUS_ATTRIBUTE_ARRAY * pAR = pECB->GetRequest(pECB); //Get the attribute array
  32. if (pAR != NULL) //Check if the attribute array is not empty
  33. {
  34. //Initialize some variables
  35. char * username = "";
  36. char * password = "";
  37. char * uniqueId = "";
  38. char * clientIp = "";
  39. //Get the size of the attribute array
  40. DWORD size = pAR->GetSize(pAR);
  41. //Pre-init the attribute pointer
  42. const RADIUS_ATTRIBUTE * pRA;
  43. //Loop through each object in attribute array
  44. for (DWORD iAR = 0; iAR < size; iAR++)
  45. {
  46. //Get the attribute from the array
  47. pRA = pAR->AttributeAt(pAR, iAR);
  48. if (pRA != NULL) //Check if the attribute is not empty
  49. {
  50. if(pRA->dwAttrType == ratUserName) //Get the username
  51. {
  52. username = (char *) pRA->lpValue;
  53. }
  54. if(pRA->dwAttrType == ratUniqueId) //Get the request ID
  55. {
  56. uniqueId = (char *) pRA->dwValue;
  57. }
  58. if(pRA->dwAttrType == ratUserPassword) //Get the password (can be empty or "")
  59. {
  60. password = (char *) pRA->lpValue;
  61. }
  62. if(pRA->dwAttrType == ratCallingStationId) //Get the source ip address
  63. {
  64. clientIp = (char *) pRA->dwValue;
  65. }
  66. }
  67. }
  68. //Write the result to the log file
  69. char buft[2048];
  70. sprintf(buft, "Recieved Request (ID:%d) for user: %s, pass: %s",uniqueId, username, password);
  71. logger(buft);
  72. //Init a post request
  73. WinHttpClient post(L"http://192.168.2.240:8080/Implementation/SAS");
  74. //Create the request json string
  75. char dat[2000];
  76. sprintf(dat, "{\"function\":\"authenticate\",\"requestId\":%d,\"username\":\"%s\",\"password\":\"%s\"}", uniqueId, username, password);
  77. //Cast from char to string
  78. string data = string(dat);
  79. //Set request data (send json)
  80. post.SetAdditionalDataToSend((BYTE *)data.c_str(), (int) data.size());
  81. //Set request headers
  82. wchar_t szSize[50] = L"";
  83. swprintf_s(szSize, L"%d", data.size());
  84. wstring headers = L"Content-Length: ";
  85. headers += szSize;
  86. headers += L"\r\nContent-Type: application/x-www-form-urlencoded\r\n";
  87. post.SetAdditionalRequestHeaders(headers);
  88. //Set max timeout
  89. post.SetTimeouts(30000U, 30000U, 30000U, 30000U);
  90. //Execute the post request
  91. if(!post.SendHttpRequest(L"POST", true)) //If it failed log it
  92. {
  93. char answer[2048];
  94. sprintf(answer, "POST FAILED from: %s for id: %d, user: %s", clientIp, uniqueId, username);
  95. logger(answer);
  96. pECB->SetResponseType(pECB, rcAccessReject);
  97. return NO_ERROR;
  98. }
  99. else
  100. {
  101. //Set the time for our timeout loop
  102. int timeout = 30;
  103. //Pre-init the response var
  104. char * response;
  105. //Our timeout loop
  106. for(int i=1; i<=timeout; i++)
  107. {
  108. //Check if we received some content
  109. if((int) post.GetRawResponseReceivedContentLength() > 0)
  110. {
  111. //YEAHHH!! We received a response
  112. response = (char *) post.GetRawResponseContent();
  113. break; //Exit the loop
  114. }
  115. else if(i >= timeout)
  116. {
  117. //OOPS!! Still no response after our time out time
  118. pECB->SetResponseType(pECB, rcAccessReject); //Set our RADIUS response to reject
  119. return NO_ERROR; //Exit the complete function
  120. }
  121. else //Still no response and within the timeout
  122. {
  123. //Sleep for 1 second (1000 miliseconds)
  124. Sleep(1000);
  125. continue; //Continue the loop
  126. }
  127. }
  128. //Finally out of the loop
  129. //Check again if response is not empty
  130. if(sizeof(response) == 0)
  131. {
  132. //If so, exit
  133. pECB->SetResponseType(pECB, rcAccessReject); //Set our RADIUS response to reject
  134. return NO_ERROR; //Exit the complete function
  135. }
  136. //Produce a json document from the received content
  137. rapidjson::Document json;
  138. json.Parse(response);
  139. //Pre-init var
  140. int code;
  141. //Check if the received json contains the "result" key
  142. if(json.HasMember("result"))
  143. {
  144. //If so, Get it as an int
  145. if(json["result"].IsInt())
  146. {
  147. //Write it to the code var
  148. code = json["result"].GetInt();
  149. }
  150. else //If it is not an int or it failed deny the request
  151. {
  152. pECB->SetResponseType(pECB, rcAccessReject); //Set our RADIUS response to reject
  153. return NO_ERROR; //Exit the complete function
  154. }
  155. }
  156. else //If the result key doesn't exist, deny the request
  157. {
  158. pECB->SetResponseType(pECB, rcAccessReject); //Set our RADIUS response to reject
  159. return NO_ERROR; //Exit the complete function
  160. }
  161. //If the result code is 0 Allow the request
  162. if(code == 0)
  163. {
  164. char out[5000];
  165. sprintf(out, "Login SUCCES from %s for id: %d, user: %s", clientIp, uniqueId, username);
  166. logger(out);
  167. pECB->SetResponseType(pECB, rcAccessAccept); //Set our RADIUS response to accept
  168. }
  169. else //Log every other result code
  170. {
  171. char out[5000];
  172. sprintf(out, "Login FAILED from %s for id: %d, user: %s | result==> code: %d, text: %s", clientIp, uniqueId, username, code, json["resultText"].GetString());
  173. logger(out);
  174. pECB->SetResponseType(pECB, rcAccessReject); //Set our RADIUS response to reject
  175. }
  176. }
  177. }
  178. }
  179. else if (pECB->rcRequestType == rcAccountingRequest) //If request type is an accounting request
  180. {
  181. pECB->SetResponseType(pECB, rcAccountingResponse); //Then just answer it
  182. }
  183. else //If we get another request
  184. {
  185. pECB->SetResponseType(pECB, rcUnknown); //We don't know what to do with it
  186. }
  187. }
  188. return NO_ERROR; //Exit the complete function
  189. }