GCC Code Coverage Report


Directory: ./
File: pdserv/src/Session.cpp
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 212 290 73.1%
Branches: 272 851 32.0%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright 2010 Richard Hacker (lerichi at gmx dot net)
6 *
7 * This file is part of the pdserv library.
8 *
9 * The pdserv library is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * The pdserv library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *****************************************************************************/
23
24 #include "Session.h"
25 #include "Main.h"
26 #include "Debug.h"
27
28 #include <sasl/saslutil.h>
29 #include <cerrno>
30 #include <cstring> // strerror()
31 #include <log4cplus/logger.h>
32 #include <log4cplus/loggingmacros.h>
33
34 #ifdef GNUTLS_FOUND
35 # include <gnutls/x509.h>
36 # include "TLS.h"
37 #endif
38
39 using namespace PdServ;
40
41 // Initialize SASL server. There are no callbacks, as well as an
42 // empty name so that no default configuration file is searched for
43 3 const int Session::saslServerInit = sasl_server_init(NULL, NULL);
44
45 /////////////////////////////////////////////////////////////////////////////
46 124 Session::Session(const Main *m, log4cplus::Logger& log, size_t bufsize)
47 124 : main(m), log(log)
48 {
49 124 conn = 0;
50 124 p_eof = false;
51 124 p_loggedIn = false;
52
53
1/2
✓ Branch 24 taken 124 times.
✗ Branch 25 not taken.
124 main->gettime(&connectedTime);
54
1/2
✓ Branch 24 taken 124 times.
✗ Branch 25 not taken.
124 main->prepare(this);
55
56
1/2
✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
124 char* buf = new char[bufsize];
57
1/2
✓ Branch 4 taken 124 times.
✗ Branch 5 not taken.
124 setp(buf, buf + bufsize);
58 124 }
59
60 /////////////////////////////////////////////////////////////////////////////
61 248 Session::~Session()
62 {
63 124 saslDispose();
64
65 124 main->cleanup(this);
66
1/2
✓ Branch 4 taken 124 times.
✗ Branch 5 not taken.
124 delete[] pbase();
67 124 }
68
69 /////////////////////////////////////////////////////////////////////////////
70 24 bool Session::saslInit()
71 {
72
1/2
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
48 std::string remoteip = peerAddr(';');
73
1/2
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
48 std::string localip = localAddr(';');
74
75
9/18
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 24 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 24 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 24 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 24 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 24 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 24 times.
✗ Branch 31 not taken.
✓ Branch 34 taken 24 times.
✗ Branch 35 not taken.
24 LOG4CPLUS_DEBUG(log,
76 LOG4CPLUS_TEXT("Creating new login session for remoteip=")
77 << LOG4CPLUS_STRING_TO_TSTRING(remoteip)
78 << LOG4CPLUS_TEXT(" localip=")
79 << LOG4CPLUS_STRING_TO_TSTRING(localip));
80
81 // Make sure sasl_server_init() was successful
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (saslServerInit != SASL_OK) {
83 LOG4CPLUS_ERROR(log,
84 LOG4CPLUS_TEXT("Could not initialize SASL server: ")
85 << LOG4CPLUS_C_STR_TO_TSTRING(
86 sasl_errstring(saslServerInit, NULL, NULL)));
87 return true;
88 }
89
90 // Setup callbacks. Only use SASL_CB_GETOPT
91 typedef int (*cb_t)(void);
92 static const sasl_callback_t _cb[CB_SIZE] = {
93 {SASL_CB_LOG, cb_t((void*)sasl_log), 0},
94 {SASL_CB_GETOPT, cb_t((void*)sasl_getopt), 0},
95 {SASL_CB_LIST_END, 0, 0},
96 };
97
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
72 for (size_t i = 0; i < CB_SIZE-1; ++i) {
98 48 sasl_callbacks[i] = _cb[i];
99 48 sasl_callbacks[i].context = this;
100 }
101 24 sasl_callbacks[0].context = const_cast<log4cplus::Logger*>(&log);
102 24 const std::string default_realm =
103
4/8
✓ Branch 15 taken 24 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 24 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 24 times.
✗ Branch 22 not taken.
✓ Branch 27 taken 24 times.
✗ Branch 28 not taken.
48 main->config("access")["sasl"]["default_realm"].toString();
104
105 24 const std::string service_name =
106
5/10
✓ Branch 15 taken 24 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 24 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 24 times.
✗ Branch 22 not taken.
✓ Branch 27 taken 24 times.
✗ Branch 28 not taken.
✓ Branch 31 taken 24 times.
✗ Branch 32 not taken.
48 main->config("access")["sasl"]["service_name"].toString("pdserv");
107
108 // Create a new login session
109
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 22 times.
48 int result = sasl_server_new(service_name.c_str(),
110 NULL, /* serverFQDN; null = use gethostname() */
111 /* user realm, null = use gethostname() */
112 24 default_realm.empty() ? nullptr : default_realm.c_str(),
113 localip.c_str(), /* Local IP */
114 remoteip.c_str(), /* Remote IP */
115 sasl_callbacks,
116 SASL_SUCCESS_DATA,
117
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 &conn);
118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (result != SASL_OK) {
119 LOG4CPLUS_ERROR(log,
120 LOG4CPLUS_TEXT("Could not create new SASL server instance: ")
121 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errstring(result,0,0)));
122 return true;
123 }
124
125 24 return false;
126 }
127
128 /////////////////////////////////////////////////////////////////////////////
129 26 const char* Session::saslMechanisms()
130 {
131
5/8
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 2 times.
✓ Branch 9 taken 24 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 24 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 26 times.
26 if (!conn and saslInit())
132 return 0;
133
134 // Send the mechanisms back.
135 // This is a space separated list of words, no prefix or suffix
136 26 const char* mechanisms;
137 26 int result = sasl_listmech(conn,
138 NULL, // user
139 NULL, // prefix
140 NULL, // space
141 NULL, // suffix
142 &mechanisms,
143 NULL, // plen
144
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 NULL); // pcount
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (SASL_OK != result) {
146 LOG4CPLUS_ERROR(log,
147 LOG4CPLUS_TEXT("Could not create new SASL server instance: ")
148 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errstring(result,0,0)));
149 return NULL;
150 }
151
8/16
✓ Branch 8 taken 26 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 26 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 26 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 26 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 26 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 26 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 26 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 26 times.
✗ Branch 40 not taken.
26 LOG4CPLUS_DEBUG(log,
152 LOG4CPLUS_TEXT("Available SASL authentication mechanisms: ")
153 << LOG4CPLUS_C_STR_TO_TSTRING(mechanisms));
154
155 26 return mechanisms;
156 }
157
158 /////////////////////////////////////////////////////////////////////////////
159 125 void Session::saslDispose()
160 {
161 125 sasl_dispose(&conn);
162 125 p_loggedIn = false;
163 125 conn = 0;
164 125 }
165
166 /////////////////////////////////////////////////////////////////////////////
167 47 bool Session::saslProcess(
168 const char* mech, const char* response, const std::string** serverout)
169 {
170 int result;
171 47 const char* out;
172 47 unsigned int outlen;
173
174
3/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
47 unsigned int inlen = response ? strlen(response) : 0;
175 47 unsigned int buflen = inlen/4*3 + 1;
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 char clientout[buflen];
177 47 unsigned int clientoutlen;
178
179 47 *serverout = NULL;
180
181
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 47 times.
47 if (!conn) {
182 p_loggedIn = false;
183
184 if (saslInit())
185 return false;
186 }
187
188 // First decode client base64 coded response
189
1/2
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
47 result = sasl_decode64(response, inlen, clientout, buflen, &clientoutlen);
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (SASL_OK != result) {
191 LOG4CPLUS_ERROR(log,
192 LOG4CPLUS_TEXT("Could not decode client base64 coded string: ")
193 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errstring(result,0,0)));
194 return false;
195 }
196
197 47 if (clientoutlen)
198 LOG4CPLUS_TRACE(log,
199 LOG4CPLUS_TEXT("SASL: Receive client reply: ")
200 << LOG4CPLUS_STRING_TO_TSTRING(
201 std::string(clientout,clientoutlen)));
202
203 // If mech is not null, this is the first step in authentication
204 // otherwise it is another step
205
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 22 times.
47 if (mech) {
206
8/16
✓ Branch 8 taken 25 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 25 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 25 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 25 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 25 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 25 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 25 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 25 times.
✗ Branch 40 not taken.
25 LOG4CPLUS_DEBUG(log,
207 LOG4CPLUS_TEXT("Login: using mechanism ")
208 << LOG4CPLUS_C_STR_TO_TSTRING(mech));
209
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✓ Branch 6 taken 25 times.
✗ Branch 7 not taken.
25 result = sasl_server_start(conn, mech,
210 response ? clientout : 0, clientoutlen,
211 &out, &outlen);
212 }
213 else {
214
1/2
✓ Branch 4 taken 22 times.
✗ Branch 5 not taken.
22 result = sasl_server_step(conn,
215 clientout, clientoutlen,
216 &out, &outlen);
217 }
218
219
11/22
✓ Branch 8 taken 47 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 47 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 47 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 47 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 47 times.
✗ Branch 27 not taken.
✓ Branch 32 taken 47 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 47 times.
✗ Branch 37 not taken.
✓ Branch 42 taken 47 times.
✗ Branch 43 not taken.
✓ Branch 46 taken 47 times.
✗ Branch 47 not taken.
✓ Branch 50 taken 47 times.
✗ Branch 51 not taken.
47 LOG4CPLUS_DEBUG(log,
220 LOG4CPLUS_TEXT("Login: result ")
221 << result << ' ' << (void*)out << ' ' << outlen);
222
223
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 29 times.
47 if (result == SASL_OK) {
224 18 const char* str;
225 18 const void** strp = (const void**)&str;
226
227 const char* userName =
228
2/4
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
36 (SASL_OK == sasl_getprop(conn, SASL_USERNAME, strp) and str)
229
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 ? str : "unknown_user";
230
231
8/16
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 18 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 18 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 18 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 18 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 18 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 18 times.
✗ Branch 40 not taken.
18 LOG4CPLUS_INFO(log,
232 LOG4CPLUS_TEXT("Successfully logged in ")
233 << LOG4CPLUS_C_STR_TO_TSTRING(userName));
234
235
2/4
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
18 if (log.isEnabledFor(log4cplus::DEBUG_LOG_LEVEL)) {
236
1/2
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
36 std::ostringstream os;
237
238
4/8
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 11 not taken.
18 if (SASL_OK == sasl_getprop(conn, SASL_AUTHUSER, strp) and str)
239
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
18 os << " authname=" << str;
240
241
4/8
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 11 not taken.
18 if (SASL_OK == sasl_getprop(conn, SASL_MECHNAME, strp) and str)
242
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
18 os << " mechanism=" << str;
243
244
6/8
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 17 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 17 times.
✓ Branch 11 taken 1 times.
18 if (SASL_OK == sasl_getprop(conn, SASL_DEFUSERREALM, strp) and str)
245
2/4
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
17 os << " realm=" << str;
246
247
4/8
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 11 not taken.
18 if (SASL_OK == sasl_getprop(conn, SASL_IPREMOTEPORT, strp) and str)
248
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
18 os << " remoteip=" << str;
249
250
1/2
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
36 log.forcedLog(log4cplus::DEBUG_LOG_LEVEL,
251
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
36 LOG4CPLUS_STRING_TO_TSTRING(os.str()));
252 }
253
254 18 p_loggedIn = true;
255 }
256
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 25 times.
29 else if (result != SASL_CONTINUE) {
257 4 const char* str;
258 4 const void** sptr = (const void**)&str;
259
260 const char* userName =
261
2/4
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
8 (SASL_OK == sasl_getprop(conn, SASL_USERNAME, sptr) and str)
262
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 ? str : "unknown_user";
263
264 const char* authSrc =
265
2/4
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
8 (SASL_OK == sasl_getprop(conn, SASL_AUTHSOURCE, sptr) and str)
266
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 ? str : "unknown";
267
268
15/30
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 4 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 4 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 4 times.
✗ Branch 31 not taken.
✓ Branch 36 taken 4 times.
✗ Branch 37 not taken.
✓ Branch 40 taken 4 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 4 times.
✗ Branch 44 not taken.
✓ Branch 52 taken 4 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 4 times.
✗ Branch 56 not taken.
✓ Branch 59 taken 4 times.
✗ Branch 60 not taken.
✓ Branch 75 taken 4 times.
✗ Branch 76 not taken.
✓ Branch 79 taken 4 times.
✗ Branch 80 not taken.
4 LOG4CPLUS_ERROR(log,
269 LOG4CPLUS_TEXT("Login failed for user ")
270 << LOG4CPLUS_C_STR_TO_TSTRING(userName)
271 << LOG4CPLUS_TEXT(" using ")
272 << LOG4CPLUS_C_STR_TO_TSTRING(authSrc)
273 << LOG4CPLUS_TEXT(": ")
274 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errdetail(conn)));
275 4 return false;
276 }
277
278
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 18 times.
43 if (outlen) {
279 25 buflen = (outlen+2)/3*4 + 1;
280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 char outbuf[buflen];
281
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 int rv = sasl_encode64(out, outlen, outbuf, buflen, &buflen);
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 if (rv != SASL_OK) {
283 LOG4CPLUS_ERROR(log,
284 LOG4CPLUS_TEXT("Could not base64-encode string: ")
285 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errstring(rv,0,0)));
286 return false;
287 }
288
1/2
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
25 sasl_reply.assign(outbuf, buflen);
289 25 *serverout = &sasl_reply;
290 LOG4CPLUS_TRACE(log,
291 LOG4CPLUS_TEXT("SASL: Sending challenge ")
292 25 << LOG4CPLUS_STRING_TO_TSTRING(std::string(out,outlen)));
293 }
294
295 90 return result == SASL_OK;
296 }
297
298 ///////////////////////////////////////////////////////////////////////////
299 // man: sasl_log_t
300 3 int Session::sasl_log(void *context, int level,
301 const char *message)
302 {
303 log4cplus::LogLevel log4cpluslevel;
304
1/7
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
3 switch (level) {
305 case SASL_LOG_NONE: /* don't log anything */
306 log4cpluslevel = log4cplus::OFF_LOG_LEVEL;
307 break;
308
309 case SASL_LOG_ERR: /* log unusual errors (default) */
310 log4cpluslevel = log4cplus::FATAL_LOG_LEVEL;
311 break;
312
313 3 case SASL_LOG_FAIL: /* log all authentication failures */
314 3 log4cpluslevel = log4cplus::ERROR_LOG_LEVEL;
315 3 break;
316
317 case SASL_LOG_WARN: /* log non-fatal warnings */
318 log4cpluslevel = log4cplus::WARN_LOG_LEVEL;
319 break;
320
321 case SASL_LOG_NOTE: /* more verbose than LOG_WARN */
322 log4cpluslevel = log4cplus::INFO_LOG_LEVEL;
323 break;
324
325 case SASL_LOG_DEBUG: /* more verbose than LOG_NOTE */
326 log4cpluslevel = log4cplus::DEBUG_LOG_LEVEL;
327 break;
328
329 case SASL_LOG_TRACE: /* traces of internal protocols */
330 case SASL_LOG_PASS: /* traces of internal protocols, including
331 * passwords */
332 default:
333 log4cpluslevel = log4cplus::TRACE_LOG_LEVEL;
334 break;
335 }
336
337 3 log4cplus::Logger* logger = reinterpret_cast<log4cplus::Logger*>(context);
338
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
3 if (logger and logger->isEnabledFor(log4cpluslevel)) {
339
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 log4cplus::tostringstream os;
340 os << LOG4CPLUS_TEXT("SASL: ")
341
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
3 << LOG4CPLUS_C_STR_TO_TSTRING(message);
342
2/4
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
3 logger->forcedLog(log4cpluslevel, os.str(), __FILE__, __LINE__);
343 }
344
345 3 return SASL_OK;
346 }
347
348 ///////////////////////////////////////////////////////////////////////////
349 // man: sasl_getopt_t
350 182 int Session::sasl_getopt(void *context, const char* /*plugin_name*/,
351 const char *option, const char **result, unsigned *len)
352 {
353 182 int rv = SASL_BADPARAM;
354 log_debug("context=%p, option=%s, result=%p len=%p",
355 context, option, result, len);
356 182 Session* session = reinterpret_cast<Session*>(context);
357
358
2/4
✓ Branch 0 taken 182 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 182 times.
✗ Branch 3 not taken.
182 if (session and option) {
359
2/4
✓ Branch 5 taken 182 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 182 times.
✗ Branch 10 not taken.
364 SaslParam::iterator it = session->saslParam.find(option);
360
2/2
✓ Branch 6 taken 136 times.
✓ Branch 7 taken 46 times.
182 if (it == session->saslParam.end()) {
361
3/6
✓ Branch 15 taken 136 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 136 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 136 times.
✗ Branch 22 not taken.
272 Config param = session->main->config("access")["sasl"][option];
362
3/4
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 46 times.
136 if (param)
363
1/2
✓ Branch 3 taken 90 times.
✗ Branch 4 not taken.
270 it = session->saslParam.insert(
364
3/6
✓ Branch 5 taken 90 times.
✗ Branch 6 not taken.
✓ Branch 12 taken 90 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 90 times.
✗ Branch 17 not taken.
180 std::make_pair(std::string(option), param.toString()))
365 180 .first;
366 else {
367
8/16
✓ Branch 8 taken 46 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 46 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 46 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 46 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 46 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 46 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 46 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 46 times.
✗ Branch 40 not taken.
46 LOG4CPLUS_DEBUG(session->log,
368 LOG4CPLUS_TEXT("SASL parameter not specified: ")
369 << LOG4CPLUS_C_STR_TO_TSTRING(option));
370 }
371 }
372
2/2
✓ Branch 6 taken 136 times.
✓ Branch 7 taken 46 times.
182 if (it != session->saslParam.end()) {
373 136 *result = it->second.c_str();
374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
136 if (len)
375 *len = it->second.size();
376 136 rv = SASL_OK;
377 }
378 }
379
380 //#define STR(x) #x
381 //#define QUOTE(x) STR(x)
382 // if (!strcmp(option, "log_level") and rv != SASL_OK) {
383 // *result = QUOTE(SASL_LOG_PASS);
384 // log_debug("setting log level rv=%s", *result);
385 // rv = SASL_OK;
386 // }
387
388 182 return rv;
389 }
390
391 /////////////////////////////////////////////////////////////////////////////
392 93 bool Session::eof() const
393 {
394
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 93 times.
93 return p_eof;
395 }
396
397 /////////////////////////////////////////////////////////////////////////////
398 474 bool Session::loggedIn() const
399 {
400
5/6
✓ Branch 3 taken 100 times.
✓ Branch 4 taken 374 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 100 times.
✓ Branch 10 taken 51 times.
✓ Branch 11 taken 49 times.
474 return conn and p_loggedIn;
401 }
402
403 /////////////////////////////////////////////////////////////////////////////
404 int Session::overflow(int value)
405 {
406 char c = value;
407 return xsputn(&c, 1) ? c : traits_type::eof();
408 }
409
410 /////////////////////////////////////////////////////////////////////////////
411 30550 std::streamsize Session::xsputn(const char * buf, std::streamsize count)
412 {
413 30550 const char* ptr = buf;
414
415 do {
416 // Put data into buffer
417 30550 size_t n = std::min(epptr() - pptr(), count);
418 30550 std::copy(ptr, ptr + n, pptr());
419
420 // Update pointers
421 30550 pbump(n);
422 30550 ptr += n;
423 30550 count -= n;
424
425
3/8
✗ Branch 8 not taken.
✓ Branch 9 taken 30550 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 30550 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 30550 times.
30550 } while (!(pptr() == epptr() and flush(true)) and count);
426
427 30550 return ptr - buf;
428 }
429
430 /////////////////////////////////////////////////////////////////////////////
431 6474 int Session::sync()
432 {
433 6474 return flush(false);
434 }
435
436 /////////////////////////////////////////////////////////////////////////////
437 // Flush output buffer.
438 //
439 // partial: true: do only one flush pass
440 6474 int Session::flush(bool partial)
441 {
442 6474 const char* buf = pbase();
443 6474 size_t count = pptr() - buf;
444
445
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 6474 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6474 times.
6474 if (p_eof)
446 return -1;
447
2/2
✓ Branch 0 taken 5863 times.
✓ Branch 1 taken 611 times.
6474 else if (!count)
448 5863 return 0;
449
450 // log_debug("flushing %i %zu", partial, count);
451 611 ssize_t result = 0;
452 do {
453
454 611 result = write(buf, count);
455
456 // log_debug("flushing result %i", result);
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
611 if (result <= 0)
458 break;
459
460 611 buf += result;
461 611 count -= result;
462
463
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
611 } while (count and !partial);
464
465 // Copy remaining data to buffer start and
466 // update std::streambuf's current put pointer pptr()
467 611 std::copy(buf, const_cast<const char*>(pptr()), pbase());
468 611 pbump(pbase() - buf);
469
470 // Calculate EOF
471
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 611 times.
1222 p_eof |= !result
472
2/6
✓ Branch 0 taken 611 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 611 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
611 or (result < 0 and (result != -EAGAIN));
473
474
1/2
✓ Branch 0 taken 611 times.
✗ Branch 1 not taken.
611 if (result > 0)
475 611 return 0;
476
477 // Interpret EOF
478 if (!result)
479 LOG4CPLUS_INFO_STR(log,
480 LOG4CPLUS_TEXT("Client closed connection"));
481 else if (result != -EAGAIN)
482 LOG4CPLUS_ERROR(log,
483 LOG4CPLUS_TEXT("Network write() error: ")
484 << LOG4CPLUS_C_STR_TO_TSTRING(strerror(-result)));
485
486 return -1;
487 }
488
489 /////////////////////////////////////////////////////////////////////////////
490 int Session::underflow()
491 {
492 char c;
493 return xsgetn(&c, 1) == 1 ? c : traits_type::eof();
494 }
495
496 /////////////////////////////////////////////////////////////////////////////
497 6134 std::streamsize Session::xsgetn(char* s, std::streamsize n)
498 {
499 6134 const ssize_t result = read(s, n);
500
501
2/2
✓ Branch 0 taken 6041 times.
✓ Branch 1 taken 93 times.
6134 if (result > 0)
502 6041 return result;
503
504 // Calculate EOF
505
2/4
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 93 times.
✗ Branch 3 not taken.
93 if (!result and result != -EAGAIN)
506 93 p_eof = true;
507
508 // Interpret EOF
509
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 93 times.
✓ Branch 5 taken 93 times.
✗ Branch 6 not taken.
93 if (p_eof) {
510
1/2
✓ Branch 0 taken 93 times.
✗ Branch 1 not taken.
93 if (!result)
511
3/6
✓ Branch 8 taken 93 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 93 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 93 times.
✗ Branch 19 not taken.
93 LOG4CPLUS_INFO_STR(log,
512 LOG4CPLUS_TEXT("Client closed connection"));
513 else if (result != -EAGAIN)
514 LOG4CPLUS_ERROR(log,
515 LOG4CPLUS_TEXT("Network error: ")
516 << LOG4CPLUS_C_STR_TO_TSTRING(strerror(-result)));
517 }
518
519 93 return 0;
520 }
521
522 /////////////////////////////////////////////////////////////////////////////
523 /////////////////////////////////////////////////////////////////////////////
524 #ifdef GNUTLS_FOUND
525 /////////////////////////////////////////////////////////////////////////////
526 21 int Session::gnutls_verify_client(gnutls_session_t tls_session)
527 {
528 int result;
529 Session* session =
530
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 reinterpret_cast<Session*>(gnutls_session_get_ptr(tls_session));
531 21 const Blacklist& blacklist = session->main->getBlacklist();
532
533 21 unsigned int list_size = ~0U;
534 const gnutls_datum_t* certs =
535
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 gnutls_certificate_get_peers (tls_session, &list_size);
536
3/6
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
21 if (list_size == ~0U or !certs or !list_size) {
537 LOG4CPLUS_FATAL_STR(session->log,
538 LOG4CPLUS_TEXT(
539 "gnutls_certificate_get_peers() failed: "
540 "Client did not send a certificate or "
541 "there was an error retrieving it"));
542 return -1;
543 }
544 else {
545
8/16
✓ Branch 8 taken 21 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 21 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 21 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 21 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 21 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 21 times.
✗ Branch 28 not taken.
✓ Branch 31 taken 21 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 21 times.
✗ Branch 36 not taken.
21 LOG4CPLUS_INFO(session->log,
546 LOG4CPLUS_TEXT("Received ")
547 << list_size
548 << LOG4CPLUS_TEXT(" certificates from peer"));
549 }
550
551 21 gnutls_x509_crt_t raw_crt = nullptr;
552
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 result = gnutls_x509_crt_init (&raw_crt);
553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (result) {
554 LOG4CPLUS_FATAL(session->log,
555 LOG4CPLUS_TEXT("gnutls_x509_crt_init() failed: ")
556 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
557 << LOG4CPLUS_TEXT(" (")
558 << LOG4CPLUS_C_STR_TO_TSTRING(
559 gnutls_strerror_name(result))
560 << LOG4CPLUS_TEXT(")"));
561 return -1;
562 }
563 42 std::unique_ptr<gnutls_x509_crt_int, TlsDeleter> crt(raw_crt);
564
565
3/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 21 times.
61 for (unsigned int i = 0; !result and i < list_size; ++i) {
566
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 result = gnutls_x509_crt_import (crt.get(), certs++, GNUTLS_X509_FMT_DER);
567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (result) {
568 LOG4CPLUS_FATAL(session->log,
569 LOG4CPLUS_TEXT("gnutls_x509_crt_import(")
570 << i
571 << LOG4CPLUS_TEXT(") failed: ")
572 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
573 << LOG4CPLUS_TEXT(" (")
574 << LOG4CPLUS_C_STR_TO_TSTRING(
575 gnutls_strerror_name(result))
576 << LOG4CPLUS_TEXT(")"));
577 break;
578 }
579
580 40 gnutls_datum_t cinfo = { NULL, 0 };
581
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 result = gnutls_x509_crt_print(
582 crt.get(), GNUTLS_CRT_PRINT_ONELINE, &cinfo);
583
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (result == GNUTLS_E_SUCCESS) {
584
10/20
✓ Branch 8 taken 40 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 40 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 40 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 40 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 40 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 40 times.
✗ Branch 28 not taken.
✓ Branch 33 taken 40 times.
✗ Branch 34 not taken.
✓ Branch 37 taken 40 times.
✗ Branch 38 not taken.
✓ Branch 45 taken 40 times.
✗ Branch 46 not taken.
✓ Branch 49 taken 40 times.
✗ Branch 50 not taken.
40 LOG4CPLUS_INFO(session->log,
585 LOG4CPLUS_TEXT("Certificate[")
586 << i
587 << LOG4CPLUS_TEXT("].info: ")
588 << LOG4CPLUS_C_STR_TO_TSTRING((const char*)cinfo.data));
589 }
590 else {
591 LOG4CPLUS_INFO(session->log,
592 LOG4CPLUS_TEXT("gnutls_x509_crt_print(")
593 << i
594 << LOG4CPLUS_TEXT(") failed: ")
595 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
596 << LOG4CPLUS_TEXT(" (")
597 << LOG4CPLUS_C_STR_TO_TSTRING(
598 gnutls_strerror_name(result))
599 << LOG4CPLUS_TEXT(")"));
600 }
601
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 gnutls_free(cinfo.data);
602
603
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
40 if (!blacklist.empty()) {
604 unsigned char buf[100];
605 size_t len = sizeof(buf);
606 result = gnutls_x509_crt_get_key_id(crt.get(), 0, buf, &len);
607 if (result or !len) {
608 LOG4CPLUS_FATAL(session->log,
609 LOG4CPLUS_TEXT("gnutls_x509_crt_get_key_id(")
610 << i
611 << LOG4CPLUS_TEXT(") failed: ")
612 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
613 << LOG4CPLUS_TEXT(" (")
614 << LOG4CPLUS_C_STR_TO_TSTRING(
615 gnutls_strerror_name(result))
616 << LOG4CPLUS_TEXT(")"));
617 result = -1;
618 break;
619 }
620 else {
621 Blacklist::const_iterator it =
622 blacklist.find(datum_string(buf, len));
623 if (it != blacklist.end()) {
624 LOG4CPLUS_FATAL(session->log,
625 LOG4CPLUS_TEXT(
626 "Certificate is blacklisted. Public Key Id = ")
627 << LOG4CPLUS_STRING_TO_TSTRING(std::string(*it)));
628 result = -1;
629 break;
630 }
631 }
632 }
633 }
634
635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (result)
636 return result;
637
638 21 unsigned int status;
639
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 result = gnutls_certificate_verify_peers2(tls_session, &status);
640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (result) {
641 // Complain
642 LOG4CPLUS_FATAL(session->log,
643 LOG4CPLUS_TEXT("gnutls_certificate_verify_peers2() failed: ")
644 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
645 << LOG4CPLUS_TEXT(" (")
646 << LOG4CPLUS_C_STR_TO_TSTRING(
647 gnutls_strerror_name(result))
648 << LOG4CPLUS_TEXT(")"));
649 return -1;
650 }
651
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 else if (status) {
652
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 std::ostringstream os;
653
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << "Verification of peer's certificate failed: ";
654
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (status & GNUTLS_CERT_INVALID)
655
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << "Certificate is invalid";
656
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_REVOKED)
658 os << "Certificate is revoked";
659
660
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
661
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << "Certificate signer is not found";
662
663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_SIGNER_NOT_CA)
664 os << "Certificate signer is not a certification authority";
665
666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
667 os << "Certificate uses an insecure algorithm";
668
669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_NOT_ACTIVATED)
670 os << "Certificate is not activated";
671
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_EXPIRED)
673 os << "Certificate expired";
674
675
4/8
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 LOG4CPLUS_FATAL_STR(session->log,
676 LOG4CPLUS_STRING_TO_TSTRING(os.str()));
677
678 1 return -1;
679 }
680
681 20 return 0;
682 9 }
683
684 #endif
685