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.
22 #ifdef WITH_SSL /* should always be defined if this module is compiled */
31 static SSL_CTX *sslContext = NULL;
32 extern int DEBUGLEVEL;
34 static int ssl_verify_cb(int ok, X509_STORE_CTX *ctx)
38 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),
39 buffer, sizeof(buffer));
41 DEBUG(0, ("SSL: Certificate OK: %s\n", buffer));
44 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
45 DEBUG(0, ("SSL: Cert error: CA not known: %s\n", buffer));
47 case X509_V_ERR_CERT_NOT_YET_VALID:
48 DEBUG(0, ("SSL: Cert error: Cert not yet valid: %s\n", buffer));
50 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
51 DEBUG(0, ("SSL: Cert error: illegal \'not before\' field: %s\n",
54 case X509_V_ERR_CERT_HAS_EXPIRED:
55 DEBUG(0, ("SSL: Cert error: Cert expired: %s\n", buffer));
57 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
58 DEBUG(0, ("SSL: Cert error: invalid \'not after\' field: %s\n",
62 DEBUG(0, ("SSL: Cert error: unknown error %d in %s\n", ctx->error,
70 static RSA *ssl_temp_rsa_cb(SSL *ssl, int export)
72 static RSA *rsa = NULL;
75 rsa = RSA_generate_key(512, RSA_F4, NULL, NULL);
79 /* This is called before we fork. It should ask the user for the pass phrase
80 * if necessary. Error output can still go to stderr because the process
83 int sslutil_init(int isServer)
86 char *certfile, *keyfile, *ciphers, *cacertDir, *cacertFile;
88 SSL_load_error_strings();
89 SSLeay_add_ssl_algorithms();
90 switch(lp_ssl_version()){
91 case SMB_SSL_V2: sslContext = SSL_CTX_new(SSLv2_method()); break;
92 case SMB_SSL_V3: sslContext = SSL_CTX_new(SSLv3_method()); break;
94 case SMB_SSL_V23: sslContext = SSL_CTX_new(SSLv23_method()); break;
95 case SMB_SSL_TLS1: sslContext = SSL_CTX_new(TLSv1_method()); break;
97 if(sslContext == NULL){
98 err = ERR_get_error();
99 fprintf(stderr, "SSL: Error allocating context: %s\n",
100 ERR_error_string(err, NULL));
103 if(lp_ssl_compatibility()){
104 SSL_CTX_set_options(sslContext, SSL_OP_ALL);
106 certfile = isServer ? lp_ssl_cert() : lp_ssl_client_cert();
107 if((certfile == NULL || *certfile == 0) && isServer){
108 fprintf(stderr, "SSL: No cert file specified in config file!\n");
109 fprintf(stderr, "The server MUST have a certificate!\n");
112 keyfile = isServer ? lp_ssl_privkey() : lp_ssl_client_privkey();
113 if(keyfile == NULL || *keyfile == 0)
115 if(certfile != NULL && *certfile != 0){
116 if(!SSL_CTX_use_certificate_file(sslContext, certfile, SSL_FILETYPE_PEM)){
117 err = ERR_get_error();
118 fprintf(stderr, "SSL: error reading certificate from file %s: %s\n",
119 certfile, ERR_error_string(err, NULL));
122 if(!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)){
123 err = ERR_get_error();
124 fprintf(stderr, "SSL: error reading private key from file %s: %s\n",
125 keyfile, ERR_error_string(err, NULL));
128 if(!SSL_CTX_check_private_key(sslContext)){
129 err = ERR_get_error();
130 fprintf(stderr, "SSL: Private key does not match public key in cert!\n");
134 cacertDir = lp_ssl_cacertdir();
135 cacertFile = lp_ssl_cacertfile();
136 if(cacertDir != NULL && *cacertDir == 0)
138 if(cacertFile != NULL && *cacertFile == 0)
140 if(!SSL_CTX_load_verify_locations(sslContext, cacertFile, cacertDir)){
141 err = ERR_get_error();
142 fprintf(stderr, "SSL: Error error setting CA cert locations: %s\n",
143 ERR_error_string(err, NULL));
144 fprintf(stderr, "trying default locations.\n");
145 cacertFile = cacertDir = NULL;
146 if(!SSL_CTX_set_default_verify_paths(sslContext)){
147 err = ERR_get_error();
148 fprintf(stderr, "SSL: Error error setting default CA cert location: %s\n",
149 ERR_error_string(err, NULL));
153 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
154 if((ciphers = lp_ssl_ciphers()) != NULL && *ciphers != 0)
155 SSL_CTX_set_cipher_list(sslContext, ciphers);
156 if((isServer && lp_ssl_reqClientCert()) || (!isServer && lp_ssl_reqServerCert())){
157 SSL_CTX_set_verify(sslContext,
158 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
160 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, ssl_verify_cb);
162 #if 1 /* don't know what this is good for, but s_server in SSLeay does it, too */
164 SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(certfile));
170 int sslutil_accept(int fd)
175 DEBUG(0, ("SSL: internal error: more than one SSL connection (server)\n"));
178 if((ssl = SSL_new(sslContext)) == NULL){
179 err = ERR_get_error();
180 DEBUG(0, ("SSL: Error allocating handle: %s\n",
181 ERR_error_string(err, NULL)));
186 if(SSL_accept(ssl) <= 0){
187 err = ERR_get_error();
188 DEBUG(0, ("SSL: Error accepting on socket: %s\n",
189 ERR_error_string(err, NULL)));
192 DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl)));
196 int sslutil_fd_is_ssl(int fd)
201 int sslutil_connect(int fd)
206 DEBUG(0, ("SSL: internal error: more than one SSL connection (client)\n"));
209 if((ssl = SSL_new(sslContext)) == NULL){
210 err = ERR_get_error();
211 DEBUG(0, ("SSL: Error allocating handle: %s\n",
212 ERR_error_string(err, NULL)));
217 if(SSL_connect(ssl) <= 0){
218 err = ERR_get_error();
219 DEBUG(0, ("SSL: Error conencting socket: %s\n",
220 ERR_error_string(err, NULL)));
223 DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl)));
227 int sslutil_disconnect(int fd)
229 if(fd == sslFd && ssl != NULL){
237 int sslutil_negotiate_ssl(int fd, int msg_type)
239 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
240 char *reqHosts, *resignHosts;
242 reqHosts = lp_ssl_hosts();
243 resignHosts = lp_ssl_hosts_resign();
244 if(!allow_access(resignHosts, reqHosts, client_name(fd), client_addr(fd))){
248 if(msg_type != 0x81){ /* first packet must be a session request */
249 DEBUG(0, ("%s Client %s did not use session setup; access denied\n",
250 timestring(), client_addr(fd)));
251 send_smb(fd, (char *)buf);
254 buf[4] = 0x8e; /* negative session response: use SSL */
255 send_smb(fd, (char *)buf);
256 if(sslutil_accept(fd) != 0){
257 DEBUG(0, ("%s Client %s failed SSL negotiation!\n",
258 timestring(), client_addr(fd)));
265 void ssl_dummy(void) {;} /* So some compilers don't complain. */
266 #endif /* WITH_SSL */