make sure we give an error for unknown lockingX locktype bits
[Samba/gebeck_regimport.git] / source / smbd / ssl.c
blob7fcb48a95490e61ef9f757fc3cc9bc148c32d944
1 /*
2 Unix SMB/CIFS implementation.
3 SSLeay utility functions
4 Copyright (C) Christian Starkjohann <cs@obdev.at> 1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 /*
22 * since includes.h pulls in config.h which is were WITH_SSL will be
23 * defined, we want to include includes.h before testing for WITH_SSL
24 * RJS 26-Jan-1999
27 #include "includes.h"
29 #ifdef WITH_SSL /* should always be defined if this module is compiled */
31 #include <openssl/ssl.h>
32 #include <openssl/err.h>
34 BOOL sslEnabled;
35 SSL *ssl = NULL;
36 int sslFd = -1;
37 static SSL_CTX *sslContext = NULL;
38 extern int DEBUGLEVEL;
40 static int ssl_verify_cb(int ok, X509_STORE_CTX *ctx)
42 char buffer[256];
44 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),
45 buffer, sizeof(buffer));
46 if(ok){
47 DEBUG(0, ("SSL: Certificate OK: %s\n", buffer));
48 }else{
49 switch (ctx->error){
50 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
51 DEBUG(0, ("SSL: Cert error: CA not known: %s\n", buffer));
52 break;
53 case X509_V_ERR_CERT_NOT_YET_VALID:
54 DEBUG(0, ("SSL: Cert error: Cert not yet valid: %s\n", buffer));
55 break;
56 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
57 DEBUG(0, ("SSL: Cert error: illegal \'not before\' field: %s\n",
58 buffer));
59 break;
60 case X509_V_ERR_CERT_HAS_EXPIRED:
61 DEBUG(0, ("SSL: Cert error: Cert expired: %s\n", buffer));
62 break;
63 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
64 DEBUG(0, ("SSL: Cert error: invalid \'not after\' field: %s\n",
65 buffer));
66 break;
67 default:
68 DEBUG(0, ("SSL: Cert error: unknown error %d in %s\n", ctx->error,
69 buffer));
70 break;
73 return ok;
76 static RSA *ssl_temp_rsa_cb(SSL *ssl, int is_export, int keylength)
78 static RSA *rsa = NULL;
80 if(rsa == NULL)
81 rsa = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
82 return rsa;
85 /* This is called before we fork. It should ask the user for the pass phrase
86 * if necessary. Error output can still go to stderr because the process
87 * has a terminal.
89 int sslutil_init(int isServer)
91 int err, entropybytes;
92 char *certfile, *keyfile, *ciphers, *cacertDir, *cacertFile;
93 char *egdsocket, *entropyfile;
95 SSL_load_error_strings();
96 SSLeay_add_ssl_algorithms();
97 egdsocket = lp_ssl_egdsocket();
98 if (egdsocket != NULL && *egdsocket != 0)
99 RAND_egd(egdsocket);
100 entropyfile = lp_ssl_entropyfile();
101 entropybytes = lp_ssl_entropybytes();
102 if (entropyfile != NULL && *entropyfile != 0)
103 RAND_load_file(entropyfile, entropybytes);
104 switch(lp_ssl_version()){
105 case SMB_SSL_V2: sslContext = SSL_CTX_new(SSLv2_method()); break;
106 case SMB_SSL_V3: sslContext = SSL_CTX_new(SSLv3_method()); break;
107 default:
108 case SMB_SSL_V23: sslContext = SSL_CTX_new(SSLv23_method()); break;
109 case SMB_SSL_TLS1: sslContext = SSL_CTX_new(TLSv1_method()); break;
111 if(sslContext == NULL){
112 err = ERR_get_error();
113 fprintf(stderr, "SSL: Error allocating context: %s\n",
114 ERR_error_string(err, NULL));
115 exit(1);
117 if(lp_ssl_compatibility()){
118 SSL_CTX_set_options(sslContext, SSL_OP_ALL);
120 certfile = isServer ? lp_ssl_server_cert() : lp_ssl_client_cert();
121 if((certfile == NULL || *certfile == 0) && isServer){
122 fprintf(stderr, "SSL: No cert file specified in config file!\n");
123 fprintf(stderr, "The server MUST have a certificate!\n");
124 exit(1);
126 keyfile = isServer ? lp_ssl_server_privkey() : lp_ssl_client_privkey();
127 if(keyfile == NULL || *keyfile == 0)
128 keyfile = certfile;
129 if(certfile != NULL && *certfile != 0){
130 if(!SSL_CTX_use_certificate_chain_file(sslContext, certfile)){
131 err = ERR_get_error();
132 fprintf(stderr, "SSL: error reading certificate from file %s: %s\n",
133 certfile, ERR_error_string(err, NULL));
134 exit(1);
136 if(!SSL_CTX_use_PrivateKey_file(sslContext, keyfile, SSL_FILETYPE_PEM)){
137 err = ERR_get_error();
138 fprintf(stderr, "SSL: error reading private key from file %s: %s\n",
139 keyfile, ERR_error_string(err, NULL));
140 exit(1);
142 if(!SSL_CTX_check_private_key(sslContext)){
143 err = ERR_get_error();
144 fprintf(stderr, "SSL: Private key does not match public key in cert!\n");
145 exit(1);
148 cacertDir = lp_ssl_cacertdir();
149 cacertFile = lp_ssl_cacertfile();
150 if(cacertDir != NULL && *cacertDir == 0)
151 cacertDir = NULL;
152 if(cacertFile != NULL && *cacertFile == 0)
153 cacertFile = NULL;
154 if(!SSL_CTX_load_verify_locations(sslContext, cacertFile, cacertDir)){
155 err = ERR_get_error();
156 if (cacertFile || cacertDir) {
157 fprintf(stderr, "SSL: Error error setting CA cert locations: %s\n",
158 ERR_error_string(err, NULL));
159 fprintf(stderr, "trying default locations.\n");
161 cacertFile = cacertDir = NULL;
162 if(!SSL_CTX_set_default_verify_paths(sslContext)){
163 err = ERR_get_error();
164 fprintf(stderr, "SSL: Error error setting default CA cert location: %s\n",
165 ERR_error_string(err, NULL));
166 exit(1);
169 SSL_CTX_set_tmp_rsa_callback(sslContext, ssl_temp_rsa_cb);
170 if((ciphers = lp_ssl_ciphers()) != NULL && *ciphers != 0)
171 SSL_CTX_set_cipher_list(sslContext, ciphers);
172 if((isServer && lp_ssl_reqClientCert()) || (!isServer && lp_ssl_reqServerCert())){
173 SSL_CTX_set_verify(sslContext,
174 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
175 }else{
176 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, ssl_verify_cb);
178 #if 1 /* don't know what this is good for, but s_server in SSLeay does it, too */
179 if(isServer){
180 SSL_CTX_set_client_CA_list(sslContext, SSL_load_client_CA_file(certfile));
182 #endif
183 return 0;
186 int sslutil_accept(int fd)
188 int err;
190 if(ssl != NULL){
191 DEBUG(0, ("SSL: internal error: more than one SSL connection (server)\n"));
192 return -1;
194 if((ssl = SSL_new(sslContext)) == NULL){
195 err = ERR_get_error();
196 DEBUG(0, ("SSL: Error allocating handle: %s\n",
197 ERR_error_string(err, NULL)));
198 return -1;
200 SSL_set_fd(ssl, fd);
201 sslFd = fd;
202 if(SSL_accept(ssl) <= 0){
203 err = ERR_get_error();
204 DEBUG(0, ("SSL: Error accepting on socket: %s\n",
205 ERR_error_string(err, NULL)));
206 return -1;
208 DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl)));
209 return 0;
212 int sslutil_fd_is_ssl(int fd)
214 return fd == sslFd;
217 int sslutil_connect(int fd)
219 int err;
221 if(ssl != NULL){
222 DEBUG(0, ("SSL: internal error: more than one SSL connection (client)\n"));
223 return -1;
225 if((ssl = SSL_new(sslContext)) == NULL){
226 err = ERR_get_error();
227 DEBUG(0, ("SSL: Error allocating handle: %s\n",
228 ERR_error_string(err, NULL)));
229 return -1;
231 SSL_set_fd(ssl, fd);
232 sslFd = fd;
233 if(SSL_connect(ssl) <= 0){
234 err = ERR_get_error();
235 DEBUG(0, ("SSL: Error conencting socket: %s\n",
236 ERR_error_string(err, NULL)));
237 return -1;
239 DEBUG(0, ("SSL: negotiated cipher: %s\n", SSL_get_cipher(ssl)));
240 return 0;
243 int sslutil_disconnect(int fd)
245 if(fd == sslFd && ssl != NULL){
246 SSL_free(ssl);
247 ssl = NULL;
248 sslFd = -1;
250 return 0;
253 int sslutil_negotiate_ssl(int fd, int msg_type)
255 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
256 char *reqHosts, *resignHosts;
258 reqHosts = lp_ssl_hosts();
259 resignHosts = lp_ssl_hosts_resign();
260 if(!allow_access(resignHosts, reqHosts, get_socket_name(fd), get_socket_addr(fd))){
261 sslEnabled = False;
262 return 0;
264 if(msg_type != 0x81){ /* first packet must be a session request */
265 DEBUG( 0, ( "Client %s did not use session setup; access denied\n",
266 client_addr() ) );
267 if (!send_smb(fd, (char *)buf))
268 DEBUG(0, ("sslutil_negotiate_ssl: send_smb failed.\n"));
269 return -1;
271 buf[4] = 0x8e; /* negative session response: use SSL */
272 if (!send_smb(fd, (char *)buf)) {
273 DEBUG(0,("sslutil_negotiate_ssl: send_smb failed.\n"));
274 return -1;
276 if(sslutil_accept(fd) != 0){
277 DEBUG( 0, ( "Client %s failed SSL negotiation!\n", client_addr() ) );
278 return -1;
280 return 1;
283 #else /* WITH_SSL */
284 void ssl_dummy(void);
285 void ssl_dummy(void) {;} /* So some compilers don't complain. */
286 #endif /* WITH_SSL */