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