summaryrefslogtreecommitdiff
path: root/src/session-initialize-bincimap-up.cc
blob: 88dc7888d1e60f7050a7bfcda9cd7c3185b289a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
 *  @file  session-initialize-bincimap-up.cc
 *  @brief bincimap-up requires sslserver
 *  @author Andreas Aardal Hanssen, Erwin Hoffmann
 *  @date 2002-2005, 2023
 */

#include "broker.h"
#include "convert.h"
#include "globals.h"
#include "iodevice.h"
#include "iofactory.h"
#include "multilogdevice.h"
#include "operators.h"
#include "session.h"
#include "stdiodevice.h"
#include "syslogdevice.h"
#include "tools.h"

#include <charconv>
#include <map>
#include <string>

#include <fcntl.h>
#include <syslog.h>

using namespace Binc;
using std::string;

bool Session::initialize(int argc, char *argv[])
{
  IOFactory &ioFactory = IOFactory::getInstance();

  auto stdioDevice = new StdIODevice(IODevice::IsEnabled);
  stdioDevice->setFlags(IODevice::HasOutputLimit);
  stdioDevice->setMaxOutputBufferSize(TRANSFER_BUFFER_SIZE);
  ioFactory.addDevice(std::unique_ptr<IODevice>(stdioDevice));

  Session &session = Session::getInstance();

  IOFactory::getLogger().clearFlags(IODevice::FlushesOnEndl);

  // Read command line arguments
  if (!session.parseCommandLine(argc, argv)) return false;

  // Show help if asked for it
  if (session.command.help) {
    printf("%s\n", session.args.usageString().c_str());
    return false;
  }

  // Show version if asked for it
  if (session.command.version) {
    printf("Binc IMAP v" BINC_VERSION "\n");
    return false;
  }

  // Let the command line args override the global settings.
  session.assignCommandLineArgs();

  // for log input
  string ip = Tools::getenv("TCP6REMOTEIP")
                  .value_or(Tools::getenv("TCPREMOTEIP").value_or("?"));
  session.setIP(ip);

  string logtype = session.getEnv("LOG_TYPE");
  lowercase(logtype);
  trim(logtype);
  if (logtype == "" || logtype == "multilog") {
    auto device = new MultilogDevice(IODevice::IsEnabled | IODevice::FlushesOnEndl);
    ioFactory.addDevice(std::unique_ptr<IODevice>(device));
  } else if (logtype == "syslog") {
    const string f = session.getEnv("SYSLOG_FACILITY");
    int facility = 0;
    auto fcr = std::from_chars(f.c_str(), f.c_str() + f.size(), facility);

    if (fcr.ec != std::errc{}) {
      if (f == "LOG_USER")
        facility = LOG_USER;
      else if (f == "LOG_LOCAL0")
        facility = LOG_LOCAL0;
      else if (f == "LOG_LOCAL1")
        facility = LOG_LOCAL1;
      else if (f == "LOG_LOCAL2")
        facility = LOG_LOCAL2;
      else if (f == "LOG_LOCAL3")
        facility = LOG_LOCAL3;
      else if (f == "LOG_LOCAL4")
        facility = LOG_LOCAL4;
      else if (f == "LOG_LOCAL5")
        facility = LOG_LOCAL5;
      else if (f == "LOG_LOCAL6")
        facility = LOG_LOCAL6;
      else if (f == "LOG_LOCAL7")
        facility = LOG_LOCAL7;
      else
        facility = LOG_DAEMON;
    }

    auto device = new SyslogDevice(IODevice::IsEnabled | IODevice::FlushesOnEndl,
                                   "bincimap-up",
                                   LOG_NDELAY | LOG_PID,
                                   facility);
    ioFactory.addDevice(std::unique_ptr<IODevice>(device));
  }

  // Now that we know the log type, we can flush.
  IOFactory::getLogger().setFlags(IODevice::FlushesOnEndl);
  IOFactory::getLogger().setOutputLevelLimit(IODevice::LogLevel::InfoLevel);

  // imaps (port 993) -- requires sslserver with option -e

  int stls = 0;
  if (Tools::getenv("SSL_SESSION_ID")) {
    session.command.ssl = true;
    stls = -1;
    // else we will do starttls - requires new FDs
  } else if (Tools::getenv("UCSPITLS")) {
    string ucspitls = session.getEnv("UCSPITLS");
    if (ucspitls == "+") stls = 1;
    if (ucspitls == "-") stls = 0;
    if (ucspitls == "!") stls = 2;
  }

  BrokerFactory &brokerfactory = BrokerFactory::getInstance();

  brokerfactory.assign("AUTHENTICATE", std::shared_ptr<Operator>(new AuthenticateOperator()));
  brokerfactory.assign("CAPABILITY", std::shared_ptr<Operator>(new CapabilityOperator()));
  brokerfactory.assign("LOGIN", std::shared_ptr<Operator>(new LoginOperator()));
  brokerfactory.assign("LOGOUT", std::shared_ptr<Operator>(new LogoutOperator()));
  brokerfactory.assign("NOOP", std::shared_ptr<Operator>(new NoopOperator()));
  brokerfactory.assign("ID", std::shared_ptr<Operator>(new IdOperator()));
  if (stls > 0)
    brokerfactory.assign("STARTTLS", std::shared_ptr<Operator>(new StarttlsOperator()));

  bincClient.setTimeout(AUTH_TIMEOUT);

  session.setState(Session::NONAUTHENTICATED);

  // If the depot was not initialized properly, return false.
  return true;
}