2 Unix SMB/Netbios implementation.
4 SSLeay utility functions
5 Copyright (C) Christian Starkjohann <cs@obdev.at> 1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * since includes.h pulls in config.h which is were WITH_SSL will be
24 * defined, we want to include includes.h before testing for WITH_SSL
30 #ifdef WITH_SSL /* should always be defined if this module is compiled */
38 static SSL_CTX
*sslContext
= NULL
;
39 extern int DEBUGLEVEL
;
41 static int ssl_verify_cb(int ok
, X509_STORE_CTX
*ctx
)
45 X509_NAME_oneline(X509_get_issuer_name(ctx
->current_cert
),
46 buffer
, sizeof(buffer
));
48 DEBUG(0, ("SSL: Certificate OK: %s\n", buffer
));
51 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
:
52 DEBUG(0, ("SSL: Cert error: CA not known: %s\n", buffer
));
54 case X509_V_ERR_CERT_NOT_YET_VALID
:
55 DEBUG(0, ("SSL: Cert error: Cert not yet valid: %s\n", buffer
));
57 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD
:
58 DEBUG(0, ("SSL: Cert error: illegal \'not before\' field: %s\n",
61 case X509_V_ERR_CERT_HAS_EXPIRED
:
62 DEBUG(0, ("SSL: Cert error: Cert expired: %s\n", buffer
));
64 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD
:
65 DEBUG(0, ("SSL: Cert error: invalid \'not after\' field: %s\n",
69 DEBUG(0, ("SSL: Cert error: unknown error %d in %s\n", ctx
->error
,
77 static RSA
*ssl_temp_rsa_cb(SSL
*ssl
, int export
)
79 static RSA
*rsa
= NULL
;
82 rsa
= RSA_generate_key(512, RSA_F4
, NULL
, NULL
);
86 /* This is called before we fork. It should ask the user for the pass phrase
87 * if necessary. Error output can still go to stderr because the process
90 int sslutil_init(int isServer
)
93 char *certfile
, *keyfile
, *ciphers
, *cacertDir
, *cacertFile
;
95 SSL_load_error_strings();
96 SSLeay_add_ssl_algorithms();
97 switch(lp_ssl_version()){
98 case SMB_SSL_V2
: sslContext
= SSL_CTX_new(SSLv2_method()); break;
99 case SMB_SSL_V3
: sslContext
= SSL_CTX_new(SSLv3_method()); break;
101 case SMB_SSL_V23
: sslContext
= SSL_CTX_new(SSLv23_method()); break;
102 case SMB_SSL_TLS1
: sslContext
= SSL_CTX_new(TLSv1_method()); break;
104 if(sslContext
== NULL
){
105 err
= ERR_get_error();
106 fprintf(stderr
, "SSL: Error allocating context: %s\n",
107 ERR_error_string(err
, NULL
));
110 if(lp_ssl_compatibility()){
111 SSL_CTX_set_options(sslContext
, SSL_OP_ALL
);
113 certfile
= isServer
? lp_ssl_cert() : lp_ssl_client_cert();
114 if((certfile
== NULL
|| *certfile
== 0) && isServer
){
115 fprintf(stderr
, "SSL: No cert file specified in config file!\n");
116 fprintf(stderr
, "The server MUST have a certificate!\n");
119 keyfile
= isServer
? lp_ssl_privkey() : lp_ssl_client_privkey();
120 if(keyfile
== NULL
|| *keyfile
== 0)
122 if(certfile
!= NULL
&& *certfile
!= 0){
123 if(!SSL_CTX_use_certificate_file(sslContext
, certfile
, SSL_FILETYPE_PEM
)){
124 err
= ERR_get_error();
125 fprintf(stderr
, "SSL: error reading certificate from file %s: %s\n",
126 certfile
, ERR_error_string(err
, NULL
));
129 if(!SSL_CTX_use_PrivateKey_file(sslContext
, keyfile
, SSL_FILETYPE_PEM
)){
130 err
= ERR_get_error();
131 fprintf(stderr
, "SSL: error reading private key from file %s: %s\n",
132 keyfile
, ERR_error_string(err
, NULL
));
135 if(!SSL_CTX_check_private_key(sslContext
)){
136 err
= ERR_get_error();
137 fprintf(stderr
, "SSL: Private key does not match public key in cert!\n");
141 cacertDir
= lp_ssl_cacertdir();
142 cacertFile
= lp_ssl_cacertfile();
143 if(cacertDir
!= NULL
&& *cacertDir
== 0)
145 if(cacertFile
!= NULL
&& *cacertFile
== 0)
147 if(!SSL_CTX_load_verify_locations(sslContext
, cacertFile
, cacertDir
)){
148 err
= ERR_get_error();
149 fprintf(stderr
, "SSL: Error error setting CA cert locations: %s\n",
150 ERR_error_string(err
, NULL
));
151 fprintf(stderr
, "trying default locations.\n");
152 cacertFile
= cacertDir
= NULL
;
153 if(!SSL_CTX_set_default_verify_paths(sslContext
)){
154 err
= ERR_get_error();
155 fprintf(stderr
, "SSL: Error error setting default CA cert location: %s\n",
156 ERR_error_string(err
, NULL
));
160 SSL_CTX_set_tmp_rsa_callback(sslContext
, ssl_temp_rsa_cb
);
161 if((ciphers
= lp_ssl_ciphers()) != NULL
&& *ciphers
!= 0)
162 SSL_CTX_set_cipher_list(sslContext
, ciphers
);
163 if((isServer
&& lp_ssl_reqClientCert()) || (!isServer
&& lp_ssl_reqServerCert())){
164 SSL_CTX_set_verify(sslContext
,
165 SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
, ssl_verify_cb
);
167 SSL_CTX_set_verify(sslContext
, SSL_VERIFY_NONE
, ssl_verify_cb
);
169 #if 1 /* don't know what this is good for, but s_server in SSLeay does it, too */
171 SSL_CTX_set_client_CA_list(sslContext
, SSL_load_client_CA_file(certfile
));
177 int sslutil_accept(int fd
)
182 DEBUG(0, ("SSL: internal error: more than one SSL connection (server)\n"));
185 if((ssl
= SSL_new(sslContext
)) == NULL
){
186 err
= ERR_get_error();
187 DEBUG(0, ("SSL: Error allocating handle: %s\n",
188 ERR_error_string(err
, NULL
)));
193 if(SSL_accept(ssl
) <= 0){
194 err
= ERR_get_error();
195 DEBUG(0, ("SSL: Error accepting on socket: %s\n",
196 ERR_error_string(err
, NULL
)));
199 DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl
)));
203 int sslutil_fd_is_ssl(int fd
)
208 int sslutil_connect(int fd
)
213 DEBUG(0, ("SSL: internal error: more than one SSL connection (client)\n"));
216 if((ssl
= SSL_new(sslContext
)) == NULL
){
217 err
= ERR_get_error();
218 DEBUG(0, ("SSL: Error allocating handle: %s\n",
219 ERR_error_string(err
, NULL
)));
224 if(SSL_connect(ssl
) <= 0){
225 err
= ERR_get_error();
226 DEBUG(0, ("SSL: Error conencting socket: %s\n",
227 ERR_error_string(err
, NULL
)));
230 DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl
)));
234 int sslutil_disconnect(int fd
)
236 if(fd
== sslFd
&& ssl
!= NULL
){
244 int sslutil_negotiate_ssl(int fd
, int msg_type
)
246 unsigned char buf
[5] = {0x83, 0, 0, 1, 0x81};
247 char *reqHosts
, *resignHosts
;
249 reqHosts
= lp_ssl_hosts();
250 resignHosts
= lp_ssl_hosts_resign();
251 if(!allow_access(resignHosts
, reqHosts
, get_socket_name(fd
), get_socket_addr(fd
))){
255 if(msg_type
!= 0x81){ /* first packet must be a session request */
256 DEBUG( 0, ( "Client %s did not use session setup; access denied\n",
258 send_smb(fd
, (char *)buf
);
261 buf
[4] = 0x8e; /* negative session response: use SSL */
262 send_smb(fd
, (char *)buf
);
263 if(sslutil_accept(fd
) != 0){
264 DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr() ) );
271 void ssl_dummy(void);
272 void ssl_dummy(void) {;} /* So some compilers don't complain. */
273 #endif /* WITH_SSL */