1 /* An implementation of the nsd interface for OpenSSL.
2  *
3  * Copyright 2018-2021 Adiscon GmbH.
4  * Author: Andre Lorbach
5  *
6  * This file is part of the rsyslog runtime library.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *       -or-
14  *       see COPYING.ASL20 in the source distribution
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #ifndef INCLUDED_NSD_OSSL_H
24 #define INCLUDED_NSD_OSSL_H
25 
26 #include "nsd.h"
27 
28 #define NSD_OSSL_MAX_RCVBUF 16 * 1024 + 1/* TLS RFC 8449: max size of buffer for message reception */
29 
30 typedef enum {
31 	osslRtry_None = 0,	/**< no call needs to be retried */
32 	osslRtry_handshake = 1,
33 	osslRtry_recv = 2
34 } osslRtryCall_t;		/**< IDs of calls that needs to be retried */
35 
36 typedef enum {
37 	osslServer = 0,		/**< Server SSL Object */
38 	osslClient = 1		/**< Client SSL Object */
39 } osslSslState_t;
40 
41 
42 typedef nsd_if_t nsd_ossl_if_t; /* we just *implement* this interface */
43 
44 /* the nsd_ossl object */
45 struct nsd_ossl_s {
46 	BEGINobjInstance;	/* Data to implement generic object - MUST be the first data element! */
47 	nsd_t *pTcp;		/**< our aggregated nsd_ptcp data */
48 	uchar *pszConnectHost;	/**< hostname used for connect - may be used to
49 					authenticate peer if no other name given */
50 	int iMode;		/* 0 - plain tcp, 1 - TLS */
51 	int bAbortConn;		/* if set, abort conncection (fatal error had happened) */
52 	const uchar *pszCAFile;
53 	const uchar *pszKeyFile;
54 	const uchar *pszCertFile;
55 	enum {
56 		OSSL_AUTH_CERTNAME = 0,
57 		OSSL_AUTH_CERTFINGERPRINT = 1,
58 		OSSL_AUTH_CERTVALID = 2,
59 		OSSL_AUTH_CERTANON = 3
60 	} authMode;
61 	enum {
62 		OSSL_EXPIRED_PERMIT = 0,
63 		OSSL_EXPIRED_DENY = 1,
64 		OSSL_EXPIRED_WARN = 2
65 	} permitExpiredCerts;
66 	osslRtryCall_t rtryCall;/**< what must we retry? */
67 	int rtryOsslErr;	/**< store ssl error code into like SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE */
68 	int bIsInitiator;	/**< 0 if socket is the server end (listener), 1 if it is the initiator */
69 	int bHaveSess;		/* as we don't know exactly which gnutls_session values
70 					are invalid, we use this one to flag whether or
71 					not we are in a session (same as -1 for a socket
72 					meaning no sess) */
73 	int bReportAuthErr;	/* only the first auth error is to be reported, this var triggers it. Initially, it is
74 				 * set to 1 and changed to 0 after the first report. It is changed back to 1 after
75 				 * one successful authentication. */
76 	permittedPeers_t *pPermPeers; /* permitted peers */
77 	uchar *gnutlsPriorityString;	/* gnutls priority string */
78 	int DrvrVerifyDepth;		/* Verify Depth for certificate chains */
79 	short	bOurCertIsInit;	/**< 1 if our certificate is initialized and must be deinit on destruction */
80 	short	bOurKeyIsInit;	/**< 1 if our private key is initialized and must be deinit on destruction */
81 	char *pszRcvBuf;
82 	int lenRcvBuf;
83 	/**< -1: empty, 0: connection closed, 1..NSD_OSSL_MAX_RCVBUF-1: data of that size present */
84 	int ptrRcvBuf;		/**< offset for next recv operation if 0 < lenRcvBuf < NSD_OSSL_MAX_RCVBUF */
85 
86 	/* Open SSL objects */
87 //	BIO *acc;		/* OpenSSL main BIO obj */
88 	int bAnonInit; // TODO: do we really need this? rger, 2021-07-07
89 	int ctx_is_copy;
90 	SSL_CTX *ctx;		/* credentials, ciphers, ... */
91 	SSL *ssl;		/* OpenSSL main SSL obj */
92 	osslSslState_t sslState;/**< what must we retry? */
93 };
94 
95 /* interface is defined in nsd.h, we just implement it! */
96 #define nsd_osslCURR_IF_VERSION nsdCURR_IF_VERSION
97 
98 /* prototypes */
99 PROTOTYPEObj(nsd_ossl);
100 
101 /* some prototypes for things used by our nsdsel_ossl helper class */
102 uchar *osslStrerror(int error);
103 rsRetVal osslChkPeerAuth(nsd_ossl_t *pThis);
104 rsRetVal osslRecordRecv(nsd_ossl_t *pThis);
105 rsRetVal osslHandshakeCheck(nsd_ossl_t *pNsd);
106 
107 /* some more prototypes to avoid warnings ... */
108 void osslLastSSLErrorMsg(int ret, SSL *ssl, int severity, const char* pszCallSource);
109 int verify_callback(int status, X509_STORE_CTX *store);
110 rsRetVal osslPostHandshakeCheck(nsd_ossl_t *pNsd);
111 
112 int opensslh_THREAD_setup(void);
113 int opensslh_THREAD_cleanup(void);
114 
115 /*-----------------------------------------------------------------------------*/
116 #define MUTEX_TYPE       pthread_mutex_t
117 #define MUTEX_SETUP(x)   pthread_mutex_init(&(x), NULL)
118 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
119 #define MUTEX_LOCK(x)    pthread_mutex_lock(&(x))
120 #define MUTEX_UNLOCK(x)  pthread_mutex_unlock(&(x))
121 #define THREAD_ID        pthread_self()
122 
123 /* This array will store all of the mutexes available to OpenSSL. */
124 struct CRYPTO_dynlock_value
125 {
126 	MUTEX_TYPE mutex;
127 };
128 
129 void dyn_destroy_function(struct CRYPTO_dynlock_value *l,
130 	__attribute__((unused)) const char *file, __attribute__((unused)) int line);
131 void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
132 	__attribute__((unused)) const char *file, __attribute__((unused)) int line);
133 struct CRYPTO_dynlock_value * dyn_create_function(
134 	__attribute__((unused)) const char *file, __attribute__((unused)) int line);
135 unsigned long id_function(void);
136 void locking_function(int mode, int n,
137 	__attribute__((unused)) const char * file, __attribute__((unused)) int line);
138 /*-----------------------------------------------------------------------------*/
139 
140 /* the name of our library binary */
141 #define LM_NSD_OSSL_FILENAME "lmnsd_ossl"
142 
143 #endif /* #ifndef INCLUDED_NSD_OSSL_H */
144