GCC Code Coverage Report


Directory: ./
File: pdserv/src/Session.cpp
Date: 2025-08-17 04:10:43
Exec Total Coverage
Lines: 214 292 73.3%
Branches: 274 851 32.2%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * Copyright 2010 Richard Hacker (lerichi at gmx dot net)
4 *
5 * This file is part of the pdserv library.
6 *
7 * The pdserv library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation, either version 3 of the License, or (at
10 * your option) any later version.
11 *
12 * The pdserv library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ****************************************************************************/
21
22 #include "Session.h"
23 #include "Main.h"
24 #include "Debug.h"
25
26 #include <sasl/saslutil.h>
27 #include <cerrno>
28 #include <cstring> // strerror()
29 #include <log4cplus/logger.h>
30 #include <log4cplus/loggingmacros.h>
31
32 #ifdef GNUTLS_FOUND
33 # include <gnutls/x509.h>
34 # include "TLS.h"
35 #endif
36
37 using namespace PdServ;
38
39 // Initialize SASL server. There are no callbacks, as well as an
40 // empty name so that no default configuration file is searched for
41 3 const int Session::saslServerInit = sasl_server_init(NULL, NULL);
42
43 /////////////////////////////////////////////////////////////////////////////
44 148 Session::Session(const Main *m, log4cplus::Logger& log, size_t bufsize)
45 148 : main(m), log(log)
46 {
47 148 conn = 0;
48 148 p_eof = false;
49 148 p_loggedIn = false;
50
51
1/2
✓ Branch 24 taken 148 times.
✗ Branch 25 not taken.
148 main->gettime(&connectedTime);
52
1/2
✓ Branch 24 taken 148 times.
✗ Branch 25 not taken.
148 main->prepare(this);
53
54
1/2
✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
148 char* buf = new char[bufsize];
55
1/2
✓ Branch 4 taken 148 times.
✗ Branch 5 not taken.
148 setp(buf, buf + bufsize);
56 148 }
57
58 /////////////////////////////////////////////////////////////////////////////
59 296 Session::~Session()
60 {
61 148 saslDispose();
62
63 148 main->cleanup(this);
64
1/2
✓ Branch 4 taken 148 times.
✗ Branch 5 not taken.
148 delete[] pbase();
65 148 }
66
67 /////////////////////////////////////////////////////////////////////////////
68 30 bool Session::saslInit()
69 {
70
1/2
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
60 std::string remoteip = peerAddr(';');
71
1/2
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
60 std::string localip = localAddr(';');
72
73
9/18
✓ Branch 8 taken 30 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 30 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 30 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 30 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 30 times.
✗ Branch 21 not taken.
✓ Branch 23 taken 30 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 30 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 30 times.
✗ Branch 31 not taken.
✓ Branch 34 taken 30 times.
✗ Branch 35 not taken.
30 LOG4CPLUS_DEBUG(log,
74 LOG4CPLUS_TEXT("Creating new login session for remoteip=")
75 << LOG4CPLUS_STRING_TO_TSTRING(remoteip)
76 << LOG4CPLUS_TEXT(" localip=")
77 << LOG4CPLUS_STRING_TO_TSTRING(localip));
78
79 // Make sure sasl_server_init() was successful
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (saslServerInit != SASL_OK) {
81 LOG4CPLUS_ERROR(log,
82 LOG4CPLUS_TEXT("Could not initialize SASL server: ")
83 << LOG4CPLUS_C_STR_TO_TSTRING(
84 sasl_errstring(saslServerInit, NULL, NULL)));
85 return true;
86 }
87
88 // Setup callbacks. Only use SASL_CB_GETOPT
89 typedef int (*cb_t)(void);
90 static const sasl_callback_t _cb[CB_SIZE] = {
91 {SASL_CB_LOG, cb_t((void*)sasl_log), 0},
92 {SASL_CB_GETOPT, cb_t((void*)sasl_getopt), 0},
93 {SASL_CB_LIST_END, 0, 0},
94 };
95
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 30 times.
90 for (size_t i = 0; i < CB_SIZE-1; ++i) {
96 60 sasl_callbacks[i] = _cb[i];
97 60 sasl_callbacks[i].context = this;
98 }
99 30 sasl_callbacks[0].context = const_cast<log4cplus::Logger*>(&log);
100 30 const std::string default_realm =
101
4/8
✓ Branch 15 taken 30 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 30 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 30 times.
✗ Branch 22 not taken.
✓ Branch 27 taken 30 times.
✗ Branch 28 not taken.
60 main->config("access")["sasl"]["default_realm"].toString();
102
103 30 const std::string service_name =
104
5/10
✓ Branch 15 taken 30 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 30 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 30 times.
✗ Branch 22 not taken.
✓ Branch 27 taken 30 times.
✗ Branch 28 not taken.
✓ Branch 31 taken 30 times.
✗ Branch 32 not taken.
60 main->config("access")["sasl"]["service_name"].toString("pdserv");
105
106 // Create a new login session
107
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 28 times.
60 int result = sasl_server_new(service_name.c_str(),
108 NULL, /* serverFQDN; null = use gethostname() */
109 /* user realm, null = use gethostname() */
110 30 default_realm.empty() ? nullptr : default_realm.c_str(),
111 localip.c_str(), /* Local IP */
112 remoteip.c_str(), /* Remote IP */
113 sasl_callbacks,
114 SASL_SUCCESS_DATA,
115
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 &conn);
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (result != SASL_OK) {
117 LOG4CPLUS_ERROR(log,
118 LOG4CPLUS_TEXT("Could not create new SASL server instance: ")
119 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errstring(result,0,0)));
120 return true;
121 }
122
123 30 return false;
124 }
125
126 /////////////////////////////////////////////////////////////////////////////
127 32 const char* Session::saslMechanisms()
128 {
129
5/8
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 2 times.
✓ Branch 9 taken 30 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 30 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 32 times.
32 if (!conn and saslInit())
130 return 0;
131
132 // Send the mechanisms back.
133 // This is a space separated list of words, no prefix or suffix
134 32 const char* mechanisms;
135 32 int result = sasl_listmech(conn,
136 NULL, // user
137 NULL, // prefix
138 NULL, // space
139 NULL, // suffix
140 &mechanisms,
141 NULL, // plen
142
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 NULL); // pcount
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (SASL_OK != result) {
144 LOG4CPLUS_ERROR(log,
145 LOG4CPLUS_TEXT("Could not create new SASL server instance: ")
146 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errstring(result,0,0)));
147 return NULL;
148 }
149
8/16
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 32 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 32 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 32 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 32 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 32 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 32 times.
✗ Branch 40 not taken.
32 LOG4CPLUS_DEBUG(log,
150 LOG4CPLUS_TEXT("Available SASL authentication mechanisms: ")
151 << LOG4CPLUS_C_STR_TO_TSTRING(mechanisms));
152
153 32 return mechanisms;
154 }
155
156 /////////////////////////////////////////////////////////////////////////////
157 149 void Session::saslDispose()
158 {
159 149 sasl_dispose(&conn);
160 149 p_loggedIn = false;
161 149 conn = 0;
162 149 }
163
164 /////////////////////////////////////////////////////////////////////////////
165 59 bool Session::saslProcess(
166 const char* mech, const char* response, const std::string** serverout)
167 {
168 int result;
169 59 const char* out;
170 59 unsigned int outlen;
171
172
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
59 unsigned int inlen = response ? strlen(response) : 0;
173 59 unsigned int buflen = inlen/4*3 + 1;
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 char clientout[buflen];
175 59 unsigned int clientoutlen;
176
177 59 *serverout = NULL;
178
179
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 59 times.
59 if (!conn) {
180 p_loggedIn = false;
181
182 if (saslInit())
183 return false;
184 }
185
186 // First decode client base64 coded response
187
1/2
✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
59 result = sasl_decode64(response, inlen, clientout, buflen, &clientoutlen);
188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (SASL_OK != result) {
189 LOG4CPLUS_ERROR(log,
190 LOG4CPLUS_TEXT("Could not decode client base64 string: ")
191 << LOG4CPLUS_C_STR_TO_TSTRING(sasl_errstring(result, 0, 0)));
192 return false;
193 }
194
195 59 if (clientoutlen)
196 LOG4CPLUS_TRACE(log,
197 LOG4CPLUS_TEXT("SASL: Receive client reply: ")
198 << LOG4CPLUS_STRING_TO_TSTRING(
199 std::string(clientout,clientoutlen)));
200
201 // If mech is not null, this is the first step in authentication
202 // otherwise it is another step
203
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 28 times.
59 if (mech) {
204
8/16
✓ Branch 8 taken 31 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 31 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 31 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 31 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 31 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 31 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 31 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 31 times.
✗ Branch 40 not taken.
31 LOG4CPLUS_DEBUG(log,
205 LOG4CPLUS_TEXT("Login: using mechanism ")
206 << LOG4CPLUS_C_STR_TO_TSTRING(mech));
207
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
✓ Branch 6 taken 31 times.
✗ Branch 7 not taken.
31 result = sasl_server_start(conn, mech,
208 response ? clientout : 0, clientoutlen,
209 &out, &outlen);
210 }
211 else {
212
1/2
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 result = sasl_server_step(conn,
213 clientout, clientoutlen,
214 &out, &outlen);
215 }
216
217
11/22
✓ Branch 8 taken 59 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 59 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 59 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 59 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 59 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 59 times.
✗ Branch 27 not taken.
✓ Branch 32 taken 59 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 59 times.
✗ Branch 37 not taken.
✓ Branch 42 taken 59 times.
✗ Branch 43 not taken.
✓ Branch 46 taken 59 times.
✗ Branch 47 not taken.
✓ Branch 50 taken 59 times.
✗ Branch 51 not taken.
59 LOG4CPLUS_DEBUG(log,
218 LOG4CPLUS_TEXT("Login: result ")
219 << result << ' ' << (void*)out << ' ' << outlen);
220
221
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 35 times.
59 if (result == SASL_OK) {
222 24 const char* str;
223 24 const void** strp = (const void**)&str;
224
225 const char* userName =
226
2/4
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
48 (SASL_OK == sasl_getprop(conn, SASL_USERNAME, strp) and str)
227
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 ? str : "unknown_user";
228
229
8/16
✓ 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 23 taken 24 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 24 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 24 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 24 times.
✗ Branch 40 not taken.
24 LOG4CPLUS_INFO(log,
230 LOG4CPLUS_TEXT("Successfully logged in ")
231 << LOG4CPLUS_C_STR_TO_TSTRING(userName));
232
233
2/4
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 24 times.
✗ Branch 10 not taken.
24 if (log.isEnabledFor(log4cplus::DEBUG_LOG_LEVEL)) {
234
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
48 std::ostringstream os;
235
236
4/8
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 11 not taken.
24 if (SASL_OK == sasl_getprop(conn, SASL_AUTHUSER, strp) and str)
237
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 os << " authname=" << str;
238
239
4/8
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 24 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 11 not taken.
24 if (SASL_OK == sasl_getprop(conn, SASL_MECHNAME, strp) and str)
240
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 os << " mechanism=" << str;
241
242
3/4
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 23 times.
✓ Branch 7 taken 1 times.
48 if (SASL_OK == sasl_getprop(conn, SASL_DEFUSERREALM, strp)
243
3/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 1 times.
24 and str)
244
2/4
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23 times.
✗ Branch 5 not taken.
23 os << " realm=" << str;
245
246
2/4
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
48 if (SASL_OK == sasl_getprop(conn, SASL_IPREMOTEPORT, strp)
247
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 and str)
248
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 os << " remoteip=" << str;
249
250
1/2
✓ Branch 9 taken 24 times.
✗ Branch 10 not taken.
48 log.forcedLog(log4cplus::DEBUG_LOG_LEVEL,
251
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
48 LOG4CPLUS_STRING_TO_TSTRING(os.str()));
252 }
253
254 24 p_loggedIn = true;
255 }
256
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 31 times.
35 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 31 times.
✓ Branch 1 taken 24 times.
55 if (outlen) {
279 31 buflen = (outlen+2)/3*4 + 1;
280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 char outbuf[buflen];
281
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 int rv = sasl_encode64(out, outlen, outbuf, buflen, &buflen);
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 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 31 times.
✗ Branch 3 not taken.
31 sasl_reply.assign(outbuf, buflen);
289 31 *serverout = &sasl_reply;
290 LOG4CPLUS_TRACE(log,
291 LOG4CPLUS_TEXT("SASL: Sending challenge ")
292 31 << LOG4CPLUS_STRING_TO_TSTRING(std::string(out,outlen)));
293 }
294
295 114 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 230 int Session::sasl_getopt(void *context, const char* /*plugin_name*/,
351 const char *option, const char **result, unsigned *len)
352 {
353 230 int rv = SASL_BADPARAM;
354 log_debug("context=%p, option=%s, result=%p len=%p",
355 context, option, result, len);
356 230 Session* session = reinterpret_cast<Session*>(context);
357
358
2/4
✓ Branch 0 taken 230 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 230 times.
✗ Branch 3 not taken.
230 if (session and option) {
359
2/4
✓ Branch 5 taken 230 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 230 times.
✗ Branch 10 not taken.
460 SaslParam::iterator it = session->saslParam.find(option);
360
2/2
✓ Branch 6 taken 172 times.
✓ Branch 7 taken 58 times.
230 if (it == session->saslParam.end()) {
361
3/6
✓ Branch 15 taken 172 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 172 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 172 times.
✗ Branch 22 not taken.
344 Config param = session->main->config("access")["sasl"][option];
362
3/4
✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
✓ Branch 4 taken 58 times.
172 if (param)
363
1/2
✓ Branch 3 taken 114 times.
✗ Branch 4 not taken.
342 it = session->saslParam.insert(
364
3/6
✓ Branch 5 taken 114 times.
✗ Branch 6 not taken.
✓ Branch 12 taken 114 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 114 times.
✗ Branch 17 not taken.
228 std::make_pair(std::string(option), param.toString()))
365 228 .first;
366 else {
367
8/16
✓ Branch 8 taken 58 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 58 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 58 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 58 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 58 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 58 times.
✗ Branch 28 not taken.
✓ Branch 35 taken 58 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 58 times.
✗ Branch 40 not taken.
58 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 172 times.
✓ Branch 7 taken 58 times.
230 if (it != session->saslParam.end()) {
373 172 *result = it->second.c_str();
374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 172 times.
172 if (len)
375 *len = it->second.size();
376 172 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 230 return rv;
389 }
390
391 /////////////////////////////////////////////////////////////////////////////
392 105 bool Session::eof() const
393 {
394
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 105 times.
105 return p_eof;
395 }
396
397 /////////////////////////////////////////////////////////////////////////////
398 606 bool Session::loggedIn() const
399 {
400
5/6
✓ Branch 3 taken 142 times.
✓ Branch 4 taken 464 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 142 times.
✓ Branch 10 taken 81 times.
✓ Branch 11 taken 61 times.
606 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 72700 std::streamsize Session::xsputn(const char * buf, std::streamsize count)
412 {
413 72700 const char* ptr = buf;
414
415 do {
416 // Put data into buffer
417 72700 size_t n = std::min(epptr() - pptr(), count);
418 72700 std::copy(ptr, ptr + n, pptr());
419
420 // Update pointers
421 72700 pbump(n);
422 72700 ptr += n;
423 72700 count -= n;
424
425
5/8
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 72697 times.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 72700 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 72700 times.
72700 } while (!(pptr() == epptr() and flush(true)) and count);
426
427 72700 return ptr - buf;
428 }
429
430 /////////////////////////////////////////////////////////////////////////////
431 9680 int Session::sync()
432 {
433 9680 return flush(false);
434 }
435
436 /////////////////////////////////////////////////////////////////////////////
437 // Flush output buffer.
438 //
439 // partial: true: do only one flush pass
440 9683 int Session::flush(bool partial)
441 {
442 9683 const char* buf = pbase();
443 9683 size_t count = pptr() - buf;
444
445
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 9683 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9683 times.
9683 if (p_eof)
446 return -1;
447
2/2
✓ Branch 0 taken 8636 times.
✓ Branch 1 taken 1047 times.
9683 else if (!count)
448 8636 return 0;
449
450 // log_debug("flushing %i %zu", partial, count);
451 1047 ssize_t result = 0;
452 do {
453
454 1047 result = write(buf, count);
455
456 // log_debug("flushing result %i", result);
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1047 times.
1047 if (result <= 0)
458 break;
459
460 1047 buf += result;
461 1047 count -= result;
462
463
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1047 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1047 } while (count and !partial);
464
465 // Copy remaining data to buffer start and
466 // update std::streambuf's current put pointer pptr()
467 1047 std::copy(buf, const_cast<const char*>(pptr()), pbase());
468 1047 pbump(pbase() - buf);
469
470 // Calculate EOF
471
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1047 times.
2094 p_eof |= !result
472
2/6
✓ Branch 0 taken 1047 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1047 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1047 or (result < 0 and (result != -EAGAIN));
473
474
1/2
✓ Branch 0 taken 1047 times.
✗ Branch 1 not taken.
1047 if (result > 0)
475 1047 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 8868 std::streamsize Session::xsgetn(char* s, std::streamsize n)
498 {
499 8868 const ssize_t result = read(s, n);
500
501
2/2
✓ Branch 0 taken 8763 times.
✓ Branch 1 taken 105 times.
8868 if (result > 0)
502 8763 return result;
503
504 // Calculate EOF
505
2/4
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 105 times.
✗ Branch 3 not taken.
105 if (!result and result != -EAGAIN)
506 105 p_eof = true;
507
508 // Interpret EOF
509
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 105 times.
✓ Branch 5 taken 105 times.
✗ Branch 6 not taken.
105 if (p_eof) {
510
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 if (!result)
511
3/6
✓ Branch 8 taken 105 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 105 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 105 times.
✗ Branch 19 not taken.
105 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 105 return 0;
520 }
521
522 /////////////////////////////////////////////////////////////////////////////
523 /////////////////////////////////////////////////////////////////////////////
524 #ifdef GNUTLS_FOUND
525 /////////////////////////////////////////////////////////////////////////////
526 27 int Session::gnutls_verify_client(gnutls_session_t tls_session)
527 {
528 int result;
529 Session* session =
530
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 reinterpret_cast<Session*>(gnutls_session_get_ptr(tls_session));
531 27 const Blacklist& blacklist = session->main->getBlacklist();
532
533 27 unsigned int list_size = ~0U;
534 const gnutls_datum_t* certs =
535
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 gnutls_certificate_get_peers (tls_session, &list_size);
536
3/6
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 27 times.
27 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 27 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 27 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 27 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 27 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 27 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 27 times.
✗ Branch 28 not taken.
✓ Branch 31 taken 27 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 27 times.
✗ Branch 36 not taken.
27 LOG4CPLUS_INFO(session->log,
546 LOG4CPLUS_TEXT("Received ")
547 << list_size
548 << LOG4CPLUS_TEXT(" certificates from peer"));
549 }
550
551 27 gnutls_x509_crt_t raw_crt = nullptr;
552
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 result = gnutls_x509_crt_init (&raw_crt);
553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 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 54 std::unique_ptr<gnutls_x509_crt_int, TlsDeleter> crt(raw_crt);
564
565
3/4
✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✓ Branch 3 taken 27 times.
79 for (unsigned int i = 0; !result and i < list_size; ++i) {
566
1/2
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
52 result = gnutls_x509_crt_import (crt.get(), certs++,
567 GNUTLS_X509_FMT_DER);
568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if (result) {
569 LOG4CPLUS_FATAL(session->log,
570 LOG4CPLUS_TEXT("gnutls_x509_crt_import(")
571 << i
572 << LOG4CPLUS_TEXT(") failed: ")
573 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
574 << LOG4CPLUS_TEXT(" (")
575 << LOG4CPLUS_C_STR_TO_TSTRING(
576 gnutls_strerror_name(result))
577 << LOG4CPLUS_TEXT(")"));
578 break;
579 }
580
581 52 gnutls_datum_t cinfo = { NULL, 0 };
582
1/2
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
52 result = gnutls_x509_crt_print(
583 crt.get(), GNUTLS_CRT_PRINT_ONELINE, &cinfo);
584
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (result == GNUTLS_E_SUCCESS) {
585
10/20
✓ Branch 8 taken 52 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 52 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 52 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 52 times.
✗ Branch 18 not taken.
✓ Branch 23 taken 52 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 52 times.
✗ Branch 28 not taken.
✓ Branch 33 taken 52 times.
✗ Branch 34 not taken.
✓ Branch 37 taken 52 times.
✗ Branch 38 not taken.
✓ Branch 45 taken 52 times.
✗ Branch 46 not taken.
✓ Branch 49 taken 52 times.
✗ Branch 50 not taken.
52 LOG4CPLUS_INFO(session->log,
586 LOG4CPLUS_TEXT("Certificate[")
587 << i
588 << LOG4CPLUS_TEXT("].info: ")
589 << LOG4CPLUS_C_STR_TO_TSTRING((const char*)cinfo.data));
590 }
591 else {
592 LOG4CPLUS_INFO(session->log,
593 LOG4CPLUS_TEXT("gnutls_x509_crt_print(")
594 << i
595 << LOG4CPLUS_TEXT(") failed: ")
596 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
597 << LOG4CPLUS_TEXT(" (")
598 << LOG4CPLUS_C_STR_TO_TSTRING(
599 gnutls_strerror_name(result))
600 << LOG4CPLUS_TEXT(")"));
601 }
602
1/2
✓ Branch 1 taken 52 times.
✗ Branch 2 not taken.
52 gnutls_free(cinfo.data);
603
604
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 52 times.
52 if (!blacklist.empty()) {
605 unsigned char buf[100];
606 size_t len = sizeof(buf);
607 result = gnutls_x509_crt_get_key_id(crt.get(), 0, buf, &len);
608 if (result or !len) {
609 LOG4CPLUS_FATAL(session->log,
610 LOG4CPLUS_TEXT("gnutls_x509_crt_get_key_id(")
611 << i
612 << LOG4CPLUS_TEXT(") failed: ")
613 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
614 << LOG4CPLUS_TEXT(" (")
615 << LOG4CPLUS_C_STR_TO_TSTRING(
616 gnutls_strerror_name(result))
617 << LOG4CPLUS_TEXT(")"));
618 result = -1;
619 break;
620 }
621 else {
622 Blacklist::const_iterator it =
623 blacklist.find(datum_string(buf, len));
624 if (it != blacklist.end()) {
625 LOG4CPLUS_FATAL(session->log,
626 LOG4CPLUS_TEXT(
627 "Certificate is blacklisted."
628 " Public Key Id = ")
629 << LOG4CPLUS_STRING_TO_TSTRING(std::string(*it)));
630 result = -1;
631 break;
632 }
633 }
634 }
635 }
636
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (result)
638 return result;
639
640 27 unsigned int status;
641
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 result = gnutls_certificate_verify_peers2(tls_session, &status);
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (result) {
643 // Complain
644 LOG4CPLUS_FATAL(session->log,
645 LOG4CPLUS_TEXT("gnutls_certificate_verify_peers2() failed: ")
646 << LOG4CPLUS_C_STR_TO_TSTRING(gnutls_strerror(result))
647 << LOG4CPLUS_TEXT(" (")
648 << LOG4CPLUS_C_STR_TO_TSTRING(
649 gnutls_strerror_name(result))
650 << LOG4CPLUS_TEXT(")"));
651 return -1;
652 }
653
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 26 times.
27 else if (status) {
654
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 std::ostringstream os;
655
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << "Verification of peer's certificate failed: ";
656
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (status & GNUTLS_CERT_INVALID)
657
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << "Certificate is invalid";
658
659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_REVOKED)
660 os << "Certificate is revoked";
661
662
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
663
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 os << "Certificate signer is not found";
664
665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_SIGNER_NOT_CA)
666 os << "Certificate signer is not a certification authority";
667
668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
669 os << "Certificate uses an insecure algorithm";
670
671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_NOT_ACTIVATED)
672 os << "Certificate is not activated";
673
674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (status & GNUTLS_CERT_EXPIRED)
675 os << "Certificate expired";
676
677
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,
678 LOG4CPLUS_STRING_TO_TSTRING(os.str()));
679
680 1 return -1;
681 }
682
683 26 return 0;
684 9 }
685
686 #endif
687