sslsniff.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (c) 2002-2009 Moxie Marlinspike
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 3 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  17. * USA
  18. */
  19. #include <openssl/ssl.h>
  20. #include <string>
  21. #include <sys/types.h>
  22. #include <unistd.h>
  23. #include <boost/asio.hpp>
  24. #include "SSLConnectionManager.hpp"
  25. #include "UpdateManager.hpp"
  26. #include "http/HttpConnectionManager.hpp"
  27. #include "certificate/TargetedCertificateManager.hpp"
  28. #include "certificate/AuthorityCertificateManager.hpp"
  29. #include "sslsniff.hpp"
  30. #include "Logger.hpp"
  31. #include "FingerprintManager.hpp"
  32. static void printUsage(char *command) {
  33. fprintf(stderr, "Usage: %s [options]\n\n"
  34. "Modes:\n"
  35. "-a\tAuthority mode. Specify a certificate that will act as a CA.\n"
  36. "-t\tTargeted mode. Specify a directory full of certificates to target.\n\n"
  37. "Required Options:\n"
  38. "-c <file|directory>\tFile containing CA cert/key (authority mode) or \n\t\t\tdirectory containing a collection of certs/keys\n\t\t\t(targeted mode)\n"
  39. "-s <port>\t\tPort to listen on for SSL interception.\n"
  40. "-w <file>\t\tFile to log to\n"
  41. "\nOptional Options:\n"
  42. "-u <updateLocation>\tLoction of any Firefox XML update files.\n"
  43. "-m <certificateChain>\tLocation of any intermediary certificates.\n"
  44. "-h <port>\t\tPort to listen on for HTTP interception (required for\n\t\t\tfingerprinting).\n"
  45. "-f <ff,ie,safari,opera,ios>\tOnly intercept requests from the specified browser(s).\n"
  46. "-d\t\t\tDeny OCSP requests for our certificates.\n"
  47. "-p\t\t\tOnly log HTTP POSTs\n"
  48. "-e <url>\t\tIntercept Mozilla Addon Updates\n"
  49. "-j <sha256>\t\tThe sha256sum value of the addon to inject\n\n", command);
  50. exit(1);
  51. }
  52. static bool isOptionsValid(Options &options) {
  53. if (options.certificateLocation.empty() ||
  54. options.sslListenPort == -1 ||
  55. options.logLocation.empty()) return false; // No cert, listen port, or log.
  56. else if (options.httpListenPort == -1 &&
  57. !options.fingerprintList.empty()) return false; // Fingerprinting but no http port.
  58. else if (options.httpListenPort != -1 &&
  59. options.fingerprintList.empty()) return false; // Http port but no fingerprinting.
  60. else if (!options.addonLocation.empty() &&
  61. options.addonHash.empty()) return false;
  62. else return true;
  63. }
  64. static int parseArguments(int argc, char* argv[], Options &options) {
  65. int c;
  66. extern char *optarg;
  67. options.denyOCSP = false;
  68. options.postOnly = false;
  69. options.targetedMode = false;
  70. options.sslListenPort = -1;
  71. options.httpListenPort = -1;
  72. while ((c = getopt(argc, argv, "ats:h:c:w:f:m:u:pdj:e:")) != -1) {
  73. switch (c) {
  74. case 'w': options.logLocation = std::string(optarg); break;
  75. case 'a': options.targetedMode = false; break;
  76. case 't': options.targetedMode = true; break;
  77. case 'c': options.certificateLocation = std::string(optarg); break;
  78. case 's': options.sslListenPort = atoi(optarg); break;
  79. case 'h': options.httpListenPort = atoi(optarg); break;
  80. case 'f': options.fingerprintList = std::string(optarg); break;
  81. case 'm': options.chainLocation = std::string(optarg); break;
  82. case 'p': options.postOnly = true; break;
  83. case 'u': options.updateLocation = std::string(optarg); break;
  84. case 'd': options.denyOCSP = true; break;
  85. case 'e': options.addonLocation = std::string(optarg); break;
  86. case 'j': options.addonHash = std::string(optarg); break;
  87. default:
  88. return -1;
  89. }
  90. }
  91. if (isOptionsValid(options)) return 1;
  92. else return -1;
  93. }
  94. static void initializeOpenSSL() {
  95. SSL_library_init();
  96. SSL_load_error_strings();
  97. }
  98. static void initializeLogging(Options &options) {
  99. Logger::initialize(options.logLocation, options.postOnly);
  100. }
  101. static CertificateManager* initializeCertificateManager(Options &options) {
  102. if (options.targetedMode) return new TargetedCertificateManager(options.certificateLocation,
  103. options.chainLocation);
  104. else return new AuthorityCertificateManager(options.certificateLocation,
  105. options.chainLocation);
  106. }
  107. int main(int argc, char* argv[]) {
  108. Options options;
  109. boost::asio::io_service io_service;
  110. if (parseArguments(argc, argv, options) < 0) {
  111. printUsage(argv[0]);
  112. }
  113. initializeLogging(options);
  114. initializeOpenSSL();
  115. CertificateManager *certs = initializeCertificateManager(options);
  116. FingerprintManager::getInstance()->setValidUserAgents(options.fingerprintList);
  117. UpdateManager::getInstance()->initialize(options.updateLocation, options.addonLocation, options.addonHash);
  118. HttpConnectionManager httpConnectionManager(io_service, options.httpListenPort, *certs,
  119. options.denyOCSP);
  120. SSLConnectionManager sslConnectionManager(io_service, *certs, options.sslListenPort);
  121. std::cout << "sslsniff " << VERSION << " by Moxie Marlinspike running..." << std::endl;
  122. io_service.run();
  123. return 1;
  124. }