Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

MainClass.cpp 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //
  2. // Created by robin on 8/8/15.
  3. //
  4. #include <iostream>
  5. #include <fstream>
  6. #include <sysexits.h>
  7. #include <jsoncpp/json/json.h>
  8. #include <cstring>
  9. #include "CommandLineParser.h"
  10. #include "MainClass.h"
  11. MainClass* MainClass::_instance = nullptr;
  12. MainClass *MainClass::getInstance()
  13. {
  14. return _instance;
  15. }
  16. sfsistat mlfi_header(SMFICTX *ctx)
  17. {
  18. return MainClass::getInstance()->mlfiHeader(ctx);
  19. }
  20. MainClass::MainClass(int argc, char *argv[])
  21. : _argc(argc)
  22. , _argv(argv)
  23. {
  24. _instance = this;
  25. _cryptoBusiness = std::make_shared<CryptoBusiness>();
  26. }
  27. MainClass::~MainClass()
  28. {
  29. }
  30. int MainClass::main()
  31. {
  32. CommandLineParser commandLineParser(_argc, _argv);
  33. CommandLineOption configOption("config", 'c', "Use FILE as configuration file.", "FILE", "/etc/milter-sasl/milter-sasl.json");
  34. commandLineParser.addOption(&configOption);
  35. CommandLineOption decryptOption("decrypt", 'd', "Decrypt DATA and exit. Can be specified multiple times. Use - to read from stdin.", "DATA");
  36. commandLineParser.addOption(&decryptOption);
  37. CommandLineOption helpOption("help", 'h', "Show this help.");
  38. commandLineParser.addOption(&helpOption);
  39. if (!commandLineParser.parse())
  40. {
  41. return commandLineParser.showHelp(EX_USAGE, true);
  42. }
  43. if (helpOption.isSet())
  44. {
  45. return commandLineParser.showHelp(0, false);
  46. }
  47. auto configFile = configOption.getValue();
  48. auto configResult = loadConfig(configFile);
  49. if (configResult != 0)
  50. {
  51. std::cerr << "Failed to read configuration file: " << strerror(configResult) << std::endl;
  52. return EX_NOINPUT;
  53. }
  54. else if (decryptOption.isSet())
  55. {
  56. return launchDecrypt(decryptOption.getValues());
  57. }
  58. else
  59. {
  60. return launchMilter(_defaultSocket);
  61. }
  62. }
  63. sfsistat MainClass::mlfiHeader(SMFICTX *ctx)
  64. {
  65. Json::Value root;
  66. auto auth_authen = smfi_getsymval(ctx, (char*)"{auth_authen}");
  67. if (auth_authen)
  68. {
  69. root["auth_authen"] = randomizeString(auth_authen);
  70. }
  71. auto auth_author = smfi_getsymval(ctx, (char*)"{auth_author}");
  72. if (auth_author)
  73. {
  74. root["auth_author"] = randomizeString(auth_author);
  75. }
  76. auto auth_type = smfi_getsymval(ctx, (char*)"{auth_type}");
  77. if (auth_type)
  78. {
  79. root["auth_type"] = randomizeString(auth_type);
  80. }
  81. Json::StyledWriter w;
  82. auto json = w.write(root);
  83. auto encrypted = _cryptoBusiness->encryptToHex(json);
  84. smfi_addheader(ctx, (char*)"X-Sasl-User", (char*)encrypted.c_str());
  85. return SMFIS_CONTINUE;
  86. }
  87. int MainClass::loadConfig(const std::string& filePath)
  88. {
  89. std::ifstream stream(filePath, std::ifstream::in);
  90. if (stream)
  91. {
  92. Json::Reader reader;
  93. Json::Value root;
  94. reader.parse(stream, root);
  95. _cryptoBusiness->setKey(root["key"].asString());
  96. _defaultSocket = root["socket"].asString();
  97. }
  98. return errno;
  99. }
  100. int MainClass::launchMilter(const std::string &socket)
  101. {
  102. srand(time(nullptr));
  103. struct smfiDesc smfilter =
  104. {
  105. (char*)"milter-sasl", /* filter name */
  106. SMFI_VERSION, /* version code -- do not change */
  107. SMFIF_ADDHDRS, /* flags */
  108. NULL, /* connection info filter */
  109. NULL, /* SMTP HELO command filter */
  110. NULL, /* envelope sender filter */
  111. NULL, /* envelope recipient filter */
  112. NULL, /* header filter */
  113. NULL, /* end of header */
  114. NULL, /* body block filter */
  115. mlfi_header, /* end of message */
  116. NULL, /* message aborted */
  117. NULL, /* connection cleanup */
  118. NULL, /* unknown/unimplemented SMTP commands */
  119. NULL, /* DATA command filter */
  120. NULL /* option negotiation at connection startup */
  121. };
  122. if (smfi_setconn((char*)socket.c_str()) == MI_FAILURE)
  123. {
  124. std::cerr << "smfi_setconn failed" << std::endl;
  125. return EX_UNAVAILABLE;
  126. }
  127. if (smfi_register(smfilter) == MI_FAILURE)
  128. {
  129. std::cerr << "smfi_register failed" << std::endl;
  130. return EX_UNAVAILABLE;
  131. }
  132. return smfi_main();
  133. }
  134. int MainClass::launchDecrypt(const std::vector<std::string> values)
  135. {
  136. for (auto value : values)
  137. {
  138. if (value == "-")
  139. {
  140. std::cin >> value;
  141. }
  142. std::cout << _cryptoBusiness->decryptFromHex(value) << std::endl;
  143. }
  144. return 0;
  145. }
  146. std::string MainClass::randomizeString(const std::string &str)
  147. {
  148. int cc = 2;
  149. std::string out;
  150. for (int i = 0; i < cc; ++i)
  151. {
  152. auto c = 'a' + (rand() % 26);
  153. out.push_back((char)c);
  154. }
  155. out += "|" + str + "|";
  156. for (int i = 0; i < cc; ++i)
  157. {
  158. auto c = 'a' + (rand() % 26);
  159. out.push_back((char)c);
  160. }
  161. return out;
  162. }