dllmain.cpp 6.6 KB

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