1 /* netstrms.c
2 *
3 * Work on this module begung 2008-04-23 by Rainer Gerhards.
4 *
5 * Copyright 2008-2021 Rainer Gerhards and Adiscon GmbH.
6 *
7 * This file is part of the rsyslog runtime library.
8 *
9 * The rsyslog runtime 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 by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * The rsyslog runtime library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the rsyslog runtime library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * A copy of the GPL can be found in the file "COPYING" in this distribution.
23 * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution.
24 */
25 #include "config.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <errno.h>
31
32 #include "rsyslog.h"
33 #include "module-template.h"
34 #include "obj.h"
35 #include "nsd.h"
36 #include "netstrm.h"
37 #include "nssel.h"
38 #include "nspoll.h"
39 #include "netstrms.h"
40
41 MODULE_TYPE_LIB
42 MODULE_TYPE_NOKEEP
43
44 /* static data */
45 DEFobjStaticHelpers
DEFobjCurrIf(glbl)46 DEFobjCurrIf(glbl)
47 DEFobjCurrIf(netstrm)
48
49
50 /* load our low-level driver. This must be done before any
51 * driver-specific functions (allmost all...) can be carried
52 * out. Note that the driver's .ifIsLoaded is correctly
53 * initialized by calloc() and we depend on that.
54 * WARNING: this code is mostly identical to similar code in
55 * nssel.c - TODO: abstract it and move it to some common place.
56 * rgerhards, 2008-04-18
57 */
58 static rsRetVal
59 loadDrvr(netstrms_t *pThis)
60 {
61 DEFiRet;
62 uchar *pBaseDrvrName;
63 uchar szDrvrName[48]; /* 48 shall be large enough */
64
65 pBaseDrvrName = pThis->pBaseDrvrName;
66 if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
67 pBaseDrvrName = glbl.GetDfltNetstrmDrvr();
68 if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsd_%s", pBaseDrvrName) == sizeof(szDrvrName))
69 ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
70 CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
71
72 pThis->Drvr.ifVersion = nsdCURR_IF_VERSION;
73 /* The pDrvrName+2 below is a hack to obtain the object name. It
74 * safes us to have yet another variable with the name without "lm" in
75 * front of it. If we change the module load interface, we may re-think
76 * about this hack, but for the time being it is efficient and clean
77 * enough. -- rgerhards, 2008-04-18
78 */
79 CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, szDrvrName, (void*) &pThis->Drvr));
80
81 finalize_it:
82 if(iRet != RS_RET_OK) {
83 if(pThis->pDrvrName != NULL) {
84 free(pThis->pDrvrName);
85 pThis->pDrvrName = NULL;
86 }
87 }
88 RETiRet;
89 }
90
91
92 /* Standard-Constructor */
93 BEGINobjConstruct(netstrms) /* be sure to specify the object type also in END macro! */
94 ENDobjConstruct(netstrms)
95
96
97 /* destructor for the netstrms object */
98 BEGINobjDestruct(netstrms) /* be sure to specify the object type also in END and CODESTART macros! */
99 CODESTARTobjDestruct(netstrms)
100 /* and now we must release our driver, if we got one. We use the presence of
101 * a driver name string as load indicator (because we also need that string
102 * to release the driver
103 */
104 if(pThis->pDrvrName != NULL) {
105 obj.ReleaseObj(__FILE__, pThis->pDrvrName+2, pThis->pDrvrName, (void*) &pThis->Drvr);
106 free(pThis->pDrvrName);
107 }
108 if(pThis->pszDrvrAuthMode != NULL) {
109 free(pThis->pszDrvrAuthMode);
110 pThis->pszDrvrAuthMode = NULL;
111 }
112 if(pThis->pszDrvrPermitExpiredCerts != NULL) {
113 free(pThis->pszDrvrPermitExpiredCerts);
114 pThis->pszDrvrPermitExpiredCerts = NULL;
115 }
116 free((void*)pThis->pszDrvrCAFile);
117 pThis->pszDrvrCAFile = NULL;
118 free((void*)pThis->pszDrvrKeyFile);
119 pThis->pszDrvrKeyFile = NULL;
120 free((void*)pThis->pszDrvrCertFile);
121 pThis->pszDrvrCertFile = NULL;
122 if(pThis->pBaseDrvrName != NULL) {
123 free(pThis->pBaseDrvrName);
124 pThis->pBaseDrvrName = NULL;
125 }
126 if(pThis->gnutlsPriorityString != NULL) {
127 free(pThis->gnutlsPriorityString);
128 pThis->gnutlsPriorityString = NULL;
129 }
ENDobjDestruct(netstrms)130 ENDobjDestruct(netstrms)
131
132
133 /* ConstructionFinalizer */
134 static rsRetVal
135 netstrmsConstructFinalize(netstrms_t *pThis)
136 {
137 DEFiRet;
138 ISOBJ_TYPE_assert(pThis, netstrms);
139 iRet = loadDrvr(pThis);
140 RETiRet;
141 }
142
143
144 /* set the base driver name. If the driver name
145 * is set to NULL, the previously set name is deleted but
146 * no name set again (which results in the system default being
147 * used)-- rgerhards, 2008-05-05
148 */
149 static rsRetVal
SetDrvrName(netstrms_t * pThis,uchar * pszName)150 SetDrvrName(netstrms_t *pThis, uchar *pszName)
151 {
152 DEFiRet;
153 ISOBJ_TYPE_assert(pThis, netstrms);
154 if(pThis->pBaseDrvrName != NULL) {
155 free(pThis->pBaseDrvrName);
156 pThis->pBaseDrvrName = NULL;
157 }
158
159 if(pszName != NULL) {
160 CHKmalloc(pThis->pBaseDrvrName = (uchar*) strdup((char*) pszName));
161 }
162 finalize_it:
163 RETiRet;
164 }
165
166
167 /* set the driver's permitted peers -- rgerhards, 2008-05-19 */
168 static rsRetVal
SetDrvrPermPeers(netstrms_t * pThis,permittedPeers_t * pPermPeers)169 SetDrvrPermPeers(netstrms_t *pThis, permittedPeers_t *pPermPeers)
170 {
171 DEFiRet;
172 ISOBJ_TYPE_assert(pThis, netstrms);
173 pThis->pPermPeers = pPermPeers;
174 RETiRet;
175 }
176 /* return the driver's permitted peers
177 * We use non-standard calling conventions because it makes an awful lot
178 * of sense here.
179 * rgerhards, 2008-05-19
180 */
181 static permittedPeers_t*
GetDrvrPermPeers(netstrms_t * pThis)182 GetDrvrPermPeers(netstrms_t *pThis)
183 {
184 ISOBJ_TYPE_assert(pThis, netstrms);
185 return pThis->pPermPeers;
186 }
187
188
189 /* set the driver auth mode -- rgerhards, 2008-05-19 */
190 static rsRetVal
SetDrvrAuthMode(netstrms_t * pThis,uchar * mode)191 SetDrvrAuthMode(netstrms_t *pThis, uchar *mode)
192 {
193 DEFiRet;
194 ISOBJ_TYPE_assert(pThis, netstrms);
195 CHKmalloc(pThis->pszDrvrAuthMode = (uchar*)strdup((char*)mode));
196 finalize_it:
197 RETiRet;
198 }
199
200
201 /* return the driver auth mode
202 * We use non-standard calling conventions because it makes an awful lot
203 * of sense here.
204 * rgerhards, 2008-05-19
205 */
206 static uchar*
GetDrvrAuthMode(netstrms_t * pThis)207 GetDrvrAuthMode(netstrms_t *pThis)
208 {
209 ISOBJ_TYPE_assert(pThis, netstrms);
210 return pThis->pszDrvrAuthMode;
211 }
212
213
214 /* return the driver permitexpiredcerts mode
215 * We use non-standard calling conventions because it makes an awful lot
216 * of sense here.
217 * alorbach, 2018-12-21
218 */
219 static uchar*
GetDrvrPermitExpiredCerts(netstrms_t * pThis)220 GetDrvrPermitExpiredCerts(netstrms_t *pThis)
221 {
222 ISOBJ_TYPE_assert(pThis, netstrms);
223 return pThis->pszDrvrPermitExpiredCerts;
224 }
225
226 /* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20
227 */
228 static rsRetVal
SetDrvrPermitExpiredCerts(netstrms_t * pThis,uchar * mode)229 SetDrvrPermitExpiredCerts(netstrms_t *pThis, uchar *mode)
230 {
231 DEFiRet;
232 ISOBJ_TYPE_assert(pThis, netstrms);
233 if (mode != NULL) {
234 CHKmalloc(pThis->pszDrvrPermitExpiredCerts = (uchar*) strdup((char*)mode));
235 }
236 finalize_it:
237 RETiRet;
238 }
239
240 static rsRetVal
SetDrvrTlsCAFile(netstrms_t * pThis,const uchar * mode)241 SetDrvrTlsCAFile(netstrms_t *pThis, const uchar *mode)
242 {
243 DEFiRet;
244 ISOBJ_TYPE_assert(pThis, netstrms);
245 if (mode != NULL) {
246 CHKmalloc(pThis->pszDrvrCAFile = (uchar*) strdup((char*)mode));
247 }
248 finalize_it:
249 RETiRet;
250 }
251
252 static rsRetVal
SetDrvrTlsKeyFile(netstrms_t * pThis,const uchar * mode)253 SetDrvrTlsKeyFile(netstrms_t *pThis, const uchar *mode)
254 {
255 DEFiRet;
256 ISOBJ_TYPE_assert(pThis, netstrms);
257 if (mode != NULL) {
258 CHKmalloc(pThis->pszDrvrKeyFile = (uchar*) strdup((char*)mode));
259 }
260 finalize_it:
261 RETiRet;
262 }
263
264 static rsRetVal
SetDrvrTlsCertFile(netstrms_t * pThis,const uchar * mode)265 SetDrvrTlsCertFile(netstrms_t *pThis, const uchar *mode)
266 {
267 DEFiRet;
268 ISOBJ_TYPE_assert(pThis, netstrms);
269 if (mode != NULL) {
270 CHKmalloc(pThis->pszDrvrCertFile = (uchar*) strdup((char*)mode));
271 }
272 finalize_it:
273 RETiRet;
274 }
275
276
277 /* Set the priorityString for GnuTLS
278 * PascalWithopf 2017-08-16
279 */
280 static rsRetVal
SetDrvrGnutlsPriorityString(netstrms_t * pThis,uchar * iVal)281 SetDrvrGnutlsPriorityString(netstrms_t *pThis, uchar *iVal)
282 {
283 DEFiRet;
284 ISOBJ_TYPE_assert(pThis, netstrms);
285 CHKmalloc(pThis->gnutlsPriorityString = (uchar*)strdup((char*)iVal));
286 finalize_it:
287 RETiRet;
288 }
289
290
291 /* return the priorityString for GnuTLS
292 * PascalWithopf, 2017-08-16
293 */
294 static uchar*
GetDrvrGnutlsPriorityString(netstrms_t * pThis)295 GetDrvrGnutlsPriorityString(netstrms_t *pThis)
296 {
297 ISOBJ_TYPE_assert(pThis, netstrms);
298 return pThis->gnutlsPriorityString;
299 }
300
301
302 /* set the driver mode -- rgerhards, 2008-04-30 */
303 static rsRetVal
SetDrvrMode(netstrms_t * pThis,int iMode)304 SetDrvrMode(netstrms_t *pThis, int iMode)
305 {
306 DEFiRet;
307 ISOBJ_TYPE_assert(pThis, netstrms);
308 pThis->iDrvrMode = iMode;
309 RETiRet;
310 }
311
312
313 /* return the driver mode
314 * We use non-standard calling conventions because it makes an awful lot
315 * of sense here.
316 * rgerhards, 2008-04-30
317 */
318 static int
GetDrvrMode(netstrms_t * pThis)319 GetDrvrMode(netstrms_t *pThis)
320 {
321 ISOBJ_TYPE_assert(pThis, netstrms);
322 return pThis->iDrvrMode;
323 }
324
325
326 /* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */
327 static rsRetVal
SetDrvrCheckExtendedKeyUsage(netstrms_t * pThis,int ChkExtendedKeyUsage)328 SetDrvrCheckExtendedKeyUsage(netstrms_t *pThis, int ChkExtendedKeyUsage)
329 {
330 DEFiRet;
331 ISOBJ_TYPE_assert(pThis, netstrms);
332 pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage;
333 RETiRet;
334 }
335
336
337 /* return the driver cert extended key usage check setting
338 * jvymazal, 2019-08-16
339 */
340 static int
GetDrvrCheckExtendedKeyUsage(netstrms_t * pThis)341 GetDrvrCheckExtendedKeyUsage(netstrms_t *pThis)
342 {
343 ISOBJ_TYPE_assert(pThis, netstrms);
344 return pThis->DrvrChkExtendedKeyUsage;
345 }
346
347
348 /* set the driver name checking policy -- jvymazal, 2019-08-16 */
349 static rsRetVal
SetDrvrPrioritizeSAN(netstrms_t * pThis,int prioritizeSan)350 SetDrvrPrioritizeSAN(netstrms_t *pThis, int prioritizeSan)
351 {
352 DEFiRet;
353 ISOBJ_TYPE_assert(pThis, netstrms);
354 pThis->DrvrPrioritizeSan = prioritizeSan;
355 RETiRet;
356 }
357
358
359 /* return the driver name checking policy
360 * jvymazal, 2019-08-16
361 */
362 static int
GetDrvrPrioritizeSAN(netstrms_t * pThis)363 GetDrvrPrioritizeSAN(netstrms_t *pThis)
364 {
365 ISOBJ_TYPE_assert(pThis, netstrms);
366 return pThis->DrvrPrioritizeSan;
367 }
368
369 /* set the driver TlsVerifyDepth -- alorbach, 2019-12-20 */
370 static rsRetVal
SetDrvrTlsVerifyDepth(netstrms_t * pThis,int verifyDepth)371 SetDrvrTlsVerifyDepth(netstrms_t *pThis, int verifyDepth)
372 {
373 DEFiRet;
374 ISOBJ_TYPE_assert(pThis, netstrms);
375 pThis->DrvrVerifyDepth = verifyDepth;
376 RETiRet;
377 }
378
379 /* return the driver TlsVerifyDepth
380 * alorbach, 2019-12-20
381 */
382 static int
GetDrvrTlsVerifyDepth(netstrms_t * pThis)383 GetDrvrTlsVerifyDepth(netstrms_t *pThis)
384 {
385 ISOBJ_TYPE_assert(pThis, netstrms);
386 return pThis->DrvrVerifyDepth;
387 }
388
389 static const uchar *
GetDrvrTlsCAFile(netstrms_t * pThis)390 GetDrvrTlsCAFile(netstrms_t *pThis)
391 {
392 ISOBJ_TYPE_assert(pThis, netstrms);
393 return pThis->pszDrvrCAFile;
394 }
395 static const uchar *
GetDrvrTlsKeyFile(netstrms_t * pThis)396 GetDrvrTlsKeyFile(netstrms_t *pThis)
397 {
398 ISOBJ_TYPE_assert(pThis, netstrms);
399 return pThis->pszDrvrKeyFile;
400 }
401 static const uchar *
GetDrvrTlsCertFile(netstrms_t * pThis)402 GetDrvrTlsCertFile(netstrms_t *pThis)
403 {
404 ISOBJ_TYPE_assert(pThis, netstrms);
405 return pThis->pszDrvrCertFile;
406 }
407
408 /* create an instance of a netstrm object. It is initialized with default
409 * values. The current driver is used. The caller may set netstrm properties
410 * and must call ConstructFinalize().
411 */
412 static rsRetVal
CreateStrm(netstrms_t * pThis,netstrm_t ** ppStrm)413 CreateStrm(netstrms_t *pThis, netstrm_t **ppStrm)
414 {
415 netstrm_t *pStrm = NULL;
416 DEFiRet;
417
418 CHKiRet(objUse(netstrm, DONT_LOAD_LIB));
419 CHKiRet(netstrm.Construct(&pStrm));
420 /* we copy over our driver structure. We could provide a pointer to
421 * ourselves, but that costs some performance on each driver invocation.
422 * As we already have hefty indirection (and thus performance toll), I
423 * prefer to copy over the function pointers here. -- rgerhards, 2008-04-23
424 */
425 memcpy(&pStrm->Drvr, &pThis->Drvr, sizeof(pThis->Drvr));
426 pStrm->pNS = pThis;
427
428 *ppStrm = pStrm;
429
430 finalize_it:
431 if(iRet != RS_RET_OK) {
432 if(pStrm != NULL)
433 netstrm.Destruct(&pStrm);
434 }
435 RETiRet;
436 }
437
438
439 /* queryInterface function */
440 BEGINobjQueryInterface(netstrms)
441 CODESTARTobjQueryInterface(netstrms)
442 if(pIf->ifVersion != netstrmsCURR_IF_VERSION) {/* check for current version, increment on each change */
443 ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED);
444 }
445
446 /* ok, we have the right interface, so let's fill it
447 * Please note that we may also do some backwards-compatibility
448 * work here (if we can support an older interface version - that,
449 * of course, also affects the "if" above).
450 */
451 pIf->Construct = netstrmsConstruct;
452 pIf->ConstructFinalize = netstrmsConstructFinalize;
453 pIf->Destruct = netstrmsDestruct;
454 pIf->CreateStrm = CreateStrm;
455 pIf->SetDrvrName = SetDrvrName;
456 pIf->SetDrvrMode = SetDrvrMode;
457 pIf->GetDrvrMode = GetDrvrMode;
458 pIf->SetDrvrAuthMode = SetDrvrAuthMode;
459 pIf->GetDrvrAuthMode = GetDrvrAuthMode;
460 pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts;
461 pIf->GetDrvrPermitExpiredCerts = GetDrvrPermitExpiredCerts;
462 pIf->SetDrvrGnutlsPriorityString = SetDrvrGnutlsPriorityString;
463 pIf->GetDrvrGnutlsPriorityString = GetDrvrGnutlsPriorityString;
464 pIf->SetDrvrPermPeers = SetDrvrPermPeers;
465 pIf->GetDrvrPermPeers = GetDrvrPermPeers;
466 pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage;
467 pIf->GetDrvrCheckExtendedKeyUsage = GetDrvrCheckExtendedKeyUsage;
468 pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN;
469 pIf->GetDrvrPrioritizeSAN = GetDrvrPrioritizeSAN;
470 pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth;
471 pIf->GetDrvrTlsVerifyDepth = GetDrvrTlsVerifyDepth;
472 pIf->GetDrvrTlsCAFile = GetDrvrTlsCAFile;
473 pIf->GetDrvrTlsKeyFile = GetDrvrTlsKeyFile;
474 pIf->GetDrvrTlsCertFile = GetDrvrTlsCertFile;
475 pIf->SetDrvrTlsCAFile = SetDrvrTlsCAFile;
476 pIf->SetDrvrTlsKeyFile = SetDrvrTlsKeyFile;
477 pIf->SetDrvrTlsCertFile = SetDrvrTlsCertFile;
478 finalize_it:
479 ENDobjQueryInterface(netstrms)
480
481
482 /* exit our class */
483 BEGINObjClassExit(netstrms, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */
484 CODESTARTObjClassExit(netstrms)
485 /* release objects we no longer need */
486 objRelease(glbl, CORE_COMPONENT);
487 objRelease(netstrm, DONT_LOAD_LIB);
488 ENDObjClassExit(netstrms)
489
490
491 /* Initialize the netstrms class. Must be called as the very first method
492 * before anything else is called inside this class.
493 * rgerhards, 2008-02-19
494 */
495 BEGINAbstractObjClassInit(netstrms, 1, OBJ_IS_CORE_MODULE) /* class, version */
496 /* request objects we use */
497 CHKiRet(objUse(glbl, CORE_COMPONENT));
498
499 /* set our own handlers */
500 ENDObjClassInit(netstrms)
501
502
503 /* --------------- here now comes the plumbing that makes as a library module --------------- */
504
505
506 BEGINmodExit
507 CODESTARTmodExit
508 nsselClassExit();
509 nspollClassExit();
510 netstrmsClassExit();
511 netstrmClassExit(); /* we use this object, so we must exit it after we are finished */
512 ENDmodExit
513
514
515 BEGINqueryEtryPt
516 CODESTARTqueryEtryPt
517 CODEqueryEtryPt_STD_LIB_QUERIES
518 ENDqueryEtryPt
519
520
521 BEGINmodInit()
522 CODESTARTmodInit
523 *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
524
525 /* Initialize all classes that are in our module - this includes ourselfs */
526 CHKiRet(netstrmClassInit(pModInfo));
527 CHKiRet(nsselClassInit(pModInfo));
528 CHKiRet(nspollClassInit(pModInfo));
529 CHKiRet(netstrmsClassInit(pModInfo));
530 ENDmodInit
531