~iheino+ub/+junk/nut-upsconf-docfix

« back to all changes in this revision

Viewing changes to server/netssl.c

  • Committer: Tuomas Heino
  • Author(s): Laurent Bigonville
  • Date: 2014-04-22 20:46:12 UTC
  • Revision ID: iheino+ub@cc.hut.fi-20140422204612-1x2gh3nkezfsdao4
Tags: upstream-2.7.2
ImportĀ upstreamĀ versionĀ 2.7.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* netssl.c - Interface to OpenSSL for upsd
 
2
 
 
3
   Copyright (C)
 
4
        2002    Russell Kroll <rkroll@exploits.org>
 
5
        2008    Arjen de Korte <adkorte-guest@alioth.debian.org>
 
6
 
 
7
   based on the original implementation:
 
8
 
 
9
   Copyright (C) 2002  Technorama Ltd. <oss-list-ups@technorama.net>
 
10
 
 
11
   This program is free software; you can redistribute it and/or modify
 
12
   it under the terms of the GNU General Public License as published by
 
13
   the Free Software Foundation; either version 2 of the License, or
 
14
   (at your option) any later version.
 
15
 
 
16
   This program is distributed in the hope that it will be useful,
 
17
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
   GNU General Public License for more details.
 
20
 
 
21
   You should have received a copy of the GNU General Public License
 
22
   along with this program; if not, write to the Free Software
 
23
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
24
*/
 
25
 
 
26
#include <sys/types.h>
 
27
#include <netinet/in.h>
 
28
#include <sys/socket.h>
 
29
 
 
30
#include "upsd.h"
 
31
#include "neterr.h"
 
32
#include "netssl.h"
 
33
 
 
34
#ifdef WITH_NSS
 
35
        #include <pk11pub.h>
 
36
        #include <prinit.h>
 
37
        #include <private/pprio.h>
 
38
        #include <key.h>
 
39
        #include <keyt.h>
 
40
        #include <secerr.h>
 
41
        #include <sslerr.h>
 
42
#endif /* WITH_NSS */
 
43
 
 
44
char    *certfile = NULL;
 
45
char    *certname = NULL;
 
46
char    *certpasswd = NULL;
 
47
 
 
48
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
 
49
int certrequest = 0;
 
50
#endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */
 
51
 
 
52
static int      ssl_initialized = 0;
 
53
 
 
54
#ifndef WITH_SSL
 
55
 
 
56
/* stubs for non-ssl compiles */
 
57
void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
 
58
{
 
59
        send_err(client, NUT_ERR_FEATURE_NOT_SUPPORTED);
 
60
        return;
 
61
}
 
62
 
 
63
int ssl_write(nut_ctype_t *client, const char *buf, size_t buflen)
 
64
{
 
65
        upslogx(LOG_ERR, "ssl_write called but SSL wasn't compiled in");
 
66
        return -1;
 
67
}
 
68
 
 
69
int ssl_read(nut_ctype_t *client, char *buf, size_t buflen)
 
70
{
 
71
        upslogx(LOG_ERR, "ssl_read called but SSL wasn't compiled in");
 
72
        return -1;
 
73
}
 
74
 
 
75
void ssl_init(void)
 
76
{
 
77
        ssl_initialized = 0;    /* keep gcc quiet */
 
78
}
 
79
 
 
80
void ssl_finish(nut_ctype_t *client)
 
81
{
 
82
        if (client->ssl) {
 
83
                upslogx(LOG_ERR, "ssl_finish found active SSL connection but SSL wasn't compiled in");
 
84
        }
 
85
}
 
86
 
 
87
void ssl_cleanup(void)
 
88
{
 
89
}
 
90
 
 
91
#else
 
92
 
 
93
#ifdef WITH_OPENSSL
 
94
 
 
95
static SSL_CTX  *ssl_ctx = NULL;
 
96
 
 
97
static void ssl_debug(void)
 
98
{
 
99
        int     e;
 
100
        char    errmsg[SMALLBUF];
 
101
 
 
102
        while ((e = ERR_get_error()) != 0) {
 
103
                ERR_error_string_n(e, errmsg, sizeof(errmsg));
 
104
                upsdebugx(1, "ssl_debug: %s", errmsg);
 
105
        }
 
106
}
 
107
 
 
108
static int ssl_error(SSL *ssl, int ret)
 
109
{
 
110
        int     e;
 
111
 
 
112
        e = SSL_get_error(ssl, ret);
 
113
 
 
114
        switch (e)
 
115
        {
 
116
        case SSL_ERROR_WANT_READ:
 
117
                upsdebugx(1, "ssl_error() ret=%d SSL_ERROR_WANT_READ", ret);
 
118
                break;
 
119
 
 
120
        case SSL_ERROR_WANT_WRITE:
 
121
                upsdebugx(1, "ssl_error() ret=%d SSL_ERROR_WANT_WRITE", ret);
 
122
                break;
 
123
 
 
124
        case SSL_ERROR_SYSCALL:
 
125
                if (ret == 0 && ERR_peek_error() == 0) {
 
126
                        upsdebugx(1, "ssl_error() EOF from client");
 
127
                } else {
 
128
                        upsdebugx(1, "ssl_error() ret=%d SSL_ERROR_SYSCALL", ret);
 
129
                }
 
130
                break;
 
131
 
 
132
        default:
 
133
                upsdebugx(1, "ssl_error() ret=%d SSL_ERROR %d", ret, e);
 
134
                ssl_debug();
 
135
        }
 
136
 
 
137
        return -1;
 
138
}
 
139
 
 
140
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
141
 
 
142
static CERTCertificate *cert;
 
143
static SECKEYPrivateKey *privKey;
 
144
 
 
145
static char *nss_password_callback(PK11SlotInfo *slot, PRBool retry, 
 
146
                void *arg)
 
147
{
 
148
        if (retry) {
 
149
                /* Force not inted to retrieve password many times. */
 
150
                return NULL;
 
151
        }
 
152
        upslogx(LOG_INFO, "Intend to retrieve password for %s / %s: password %sconfigured",
 
153
                PK11_GetSlotName(slot), PK11_GetTokenName(slot), certpasswd?"":"not ");
 
154
        return certpasswd ? PL_strdup(certpasswd) : NULL;
 
155
}
 
156
 
 
157
static void nss_error(const char* text)
 
158
{
 
159
        char buffer[SMALLBUF];
 
160
        PRInt32 length = PR_GetErrorText(buffer);
 
161
        if (length > 0 && length < SMALLBUF) {
 
162
                upsdebugx(1, "nss_error %ld in %s : %s", (long)PR_GetError(), text, buffer);
 
163
        }else{
 
164
                upsdebugx(1, "nss_error %ld in %s", (long)PR_GetError(), text);
 
165
        }
 
166
}
 
167
 
 
168
static int ssl_error(PRFileDesc *ssl, int ret)
 
169
{
 
170
        char buffer[256];
 
171
        PRInt32 length;
 
172
        PRErrorCode e;
 
173
        
 
174
        e = PR_GetError();
 
175
        length = PR_GetErrorText(buffer);
 
176
        if (length > 0 && length < 256) {
 
177
                upsdebugx(1, "ssl_error() ret=%d %*s", e, length, buffer);
 
178
        } else {
 
179
                upsdebugx(1, "ssl_error() ret=%d", e);
 
180
        }
 
181
 
 
182
        return -1;
 
183
}
 
184
 
 
185
static SECStatus AuthCertificate(CERTCertDBHandle *arg, PRFileDesc *fd,
 
186
        PRBool checksig, PRBool isServer)
 
187
{
 
188
        nut_ctype_t *client  = (nut_ctype_t *)SSL_RevealPinArg(fd);
 
189
        SECStatus status = SSL_AuthCertificate(arg, fd, checksig, isServer);
 
190
        upslogx(LOG_INFO, "Intend to authenticate client %s : %s.",
 
191
                client?client->addr:"(unnamed)",
 
192
                status==SECSuccess?"SUCCESS":"FAILED");
 
193
        return status;
 
194
}
 
195
 
 
196
static SECStatus BadCertHandler(nut_ctype_t *arg, PRFileDesc *fd)
 
197
{
 
198
        upslogx(LOG_WARNING, "Certificate validation failed for %s",
 
199
                (arg&&arg->addr)?arg->addr:"<unnamed>");
 
200
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
 
201
        /* BadCertHandler is called when the NSS certificate validation is failed.
 
202
         * If the certificate verification (user conf) is mandatory, reject authentication
 
203
         * else accept it.
 
204
         */ 
 
205
        return certrequest==NETSSL_CERTREQ_REQUIRE?SECFailure:SECSuccess;
 
206
#else /* WITH_CLIENT_CERTIFICATE_VALIDATION */
 
207
        /* Always accept clients. */
 
208
        return SECSuccess;
 
209
#endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */
 
210
}
 
211
 
 
212
static void HandshakeCallback(PRFileDesc *fd, nut_ctype_t *client_data)
 
213
{
 
214
        upslogx(LOG_INFO, "SSL handshake done successfully with client %s",
 
215
                client_data->addr);
 
216
}
 
217
 
 
218
 
 
219
#endif /* WITH_OPENSSL | WITH_NSS */
 
220
 
 
221
void net_starttls(nut_ctype_t *client, int numarg, const char **arg)
 
222
{
 
223
#ifdef WITH_OPENSSL
 
224
        int ret;
 
225
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
226
        SECStatus       status;
 
227
        PRFileDesc      *socket;
 
228
#endif /* WITH_OPENSSL | WITH_NSS */
 
229
        
 
230
        if (client->ssl) {
 
231
                send_err(client, NUT_ERR_ALREADY_SSL_MODE);
 
232
                return;
 
233
        }
 
234
 
 
235
        client->ssl_connected = 0;
 
236
 
 
237
        if ((!certfile) || (!ssl_initialized)) {
 
238
                send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED);
 
239
                return;
 
240
        }
 
241
        
 
242
#ifdef WITH_OPENSSL     
 
243
        if (!ssl_ctx) {
 
244
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
245
        if (!NSS_IsInitialized()) {
 
246
#endif /* WITH_OPENSSL | WITH_NSS */
 
247
                send_err(client, NUT_ERR_FEATURE_NOT_CONFIGURED);
 
248
                ssl_initialized = 0;
 
249
                return;
 
250
        }
 
251
        
 
252
        if (!sendback(client, "OK STARTTLS\n")) {
 
253
                return;
 
254
        }
 
255
 
 
256
#ifdef WITH_OPENSSL     
 
257
 
 
258
        client->ssl = SSL_new(ssl_ctx);
 
259
 
 
260
        if (!client->ssl) {
 
261
                upslog_with_errno(LOG_ERR, "SSL_new failed\n");
 
262
                ssl_debug();
 
263
                return;
 
264
        }
 
265
 
 
266
        if (SSL_set_fd(client->ssl, client->sock_fd) != 1) {
 
267
                upslog_with_errno(LOG_ERR, "SSL_set_fd failed\n");
 
268
                ssl_debug();
 
269
                return;
 
270
        }
 
271
        
 
272
        ret = SSL_accept(client->ssl);
 
273
        switch (ret)
 
274
        {
 
275
        case 1:
 
276
                client->ssl_connected = 1;
 
277
                upsdebugx(3, "SSL connected");
 
278
                break;
 
279
                
 
280
        case 0:
 
281
                upslog_with_errno(LOG_ERR, "SSL_accept do not accept handshake.");
 
282
                ssl_error(client->ssl, ret);
 
283
                break;
 
284
        case -1:
 
285
                upslog_with_errno(LOG_ERR, "Unknown return value from SSL_accept");
 
286
                ssl_error(client->ssl, ret);
 
287
                break;
 
288
        }
 
289
        
 
290
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
291
 
 
292
        socket = PR_ImportTCPSocket(client->sock_fd);
 
293
        if (socket == NULL){
 
294
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
295
                nss_error("net_starttls / PR_ImportTCPSocket");
 
296
                return;
 
297
        }
 
298
 
 
299
        client->ssl = SSL_ImportFD(NULL, socket);
 
300
        if (client->ssl == NULL){
 
301
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
302
                nss_error("net_starttls / SSL_ImportFD");
 
303
                return;
 
304
        }
 
305
        
 
306
        if (SSL_SetPKCS11PinArg(client->ssl, client) == -1){
 
307
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
308
                nss_error("net_starttls / SSL_SetPKCS11PinArg");
 
309
                return;
 
310
        }
 
311
        
 
312
        /* Note cast to SSLAuthCertificate to prevent warning due to
 
313
         * bad function prototype in NSS.
 
314
         */
 
315
        status = SSL_AuthCertificateHook(client->ssl, (SSLAuthCertificate)AuthCertificate, CERT_GetDefaultCertDB());
 
316
        if (status != SECSuccess) {
 
317
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
318
                nss_error("net_starttls / SSL_AuthCertificateHook");
 
319
                return;
 
320
        }
 
321
        
 
322
        status = SSL_BadCertHook(client->ssl, (SSLBadCertHandler)BadCertHandler, client);
 
323
        if (status != SECSuccess) {
 
324
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
325
                nss_error("net_starttls / SSL_BadCertHook");
 
326
                return;
 
327
        }
 
328
        
 
329
        status = SSL_HandshakeCallback(client->ssl, (SSLHandshakeCallback)HandshakeCallback, client);
 
330
        if (status != SECSuccess) {
 
331
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
332
                nss_error("net_starttls / SSL_HandshakeCallback");
 
333
                return;
 
334
        }
 
335
        
 
336
        status = SSL_ConfigSecureServer(client->ssl, cert, privKey, NSS_FindCertKEAType(cert));
 
337
        if (status != SECSuccess) {
 
338
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
339
                nss_error("net_starttls / SSL_ConfigSecureServer");
 
340
                return;
 
341
        }
 
342
 
 
343
        status = SSL_ResetHandshake(client->ssl, PR_TRUE);
 
344
        if (status != SECSuccess) {
 
345
                upslogx(LOG_ERR, "Can not inialize SSL connection");
 
346
                nss_error("net_starttls / SSL_ResetHandshake");
 
347
                return;
 
348
        }
 
349
 
 
350
        /* Note: this call can generate memory leaks not resolvable
 
351
         * by any release function.
 
352
         * Probably SSL session key object allocation. */
 
353
        status = SSL_ForceHandshake(client->ssl);
 
354
        if (status != SECSuccess) {
 
355
                PRErrorCode code = PR_GetError();
 
356
                if (code==SSL_ERROR_NO_CERTIFICATE) {
 
357
                        upslogx(LOG_WARNING, "Client %s do not provide certificate.",
 
358
                                client->addr);
 
359
                } else {
 
360
                        nss_error("net_starttls / SSL_ForceHandshake");
 
361
                        /* TODO : Close the connection. */
 
362
                        return;
 
363
                }
 
364
        }
 
365
        client->ssl_connected = 1;
 
366
#endif /* WITH_OPENSSL | WITH_NSS */
 
367
}
 
368
 
 
369
void ssl_init(void)
 
370
{
 
371
#ifdef WITH_NSS
 
372
        SECStatus status;
 
373
#elif defined(WITH_OPENSSL)
 
374
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
 
375
        const SSL_METHOD        *ssl_method;
 
376
#else
 
377
        SSL_METHOD      *ssl_method;
 
378
#endif
 
379
#endif /* WITH_NSS|WITH_OPENSSL */
 
380
 
 
381
        if (!certfile) {
 
382
                return;
 
383
        }
 
384
 
 
385
        check_perms(certfile);
 
386
 
 
387
#ifdef WITH_OPENSSL
 
388
 
 
389
        SSL_load_error_strings();
 
390
        SSL_library_init();
 
391
 
 
392
        if ((ssl_method = TLSv1_server_method()) == NULL) {
 
393
                ssl_debug();
 
394
                fatalx(EXIT_FAILURE, "TLSv1_server_method failed");
 
395
        }
 
396
 
 
397
        if ((ssl_ctx = SSL_CTX_new(ssl_method)) == NULL) {
 
398
                ssl_debug();
 
399
                fatalx(EXIT_FAILURE, "SSL_CTX_new failed");
 
400
        }
 
401
 
 
402
        if (SSL_CTX_use_certificate_chain_file(ssl_ctx, certfile) != 1) {
 
403
                ssl_debug();
 
404
                fatalx(EXIT_FAILURE, "SSL_CTX_use_certificate_chain_file(%s) failed", certfile);
 
405
        }
 
406
 
 
407
        if (SSL_CTX_use_PrivateKey_file(ssl_ctx, certfile, SSL_FILETYPE_PEM) != 1) {
 
408
                ssl_debug();
 
409
                fatalx(EXIT_FAILURE, "SSL_CTX_use_PrivateKey_file(%s) failed", certfile);
 
410
        }
 
411
 
 
412
        if (SSL_CTX_check_private_key(ssl_ctx) != 1) {
 
413
                ssl_debug();
 
414
                fatalx(EXIT_FAILURE, "SSL_CTX_check_private_key(%s) failed", certfile);
 
415
        }
 
416
 
 
417
        if (SSL_CTX_set_cipher_list(ssl_ctx, "HIGH:@STRENGTH") != 1) {
 
418
                ssl_debug();
 
419
                fatalx(EXIT_FAILURE, "SSL_CTX_set_cipher_list failed");
 
420
        }
 
421
 
 
422
        SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
 
423
 
 
424
        ssl_initialized = 1;
 
425
                
 
426
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
427
 
 
428
        if (!certname || certname[0]==0 ) {
 
429
                upslogx(LOG_ERR, "The SSL certificate name is not specified.");
 
430
                return;
 
431
        }
 
432
 
 
433
        PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
 
434
        
 
435
        PK11_SetPasswordFunc(nss_password_callback);
 
436
        
 
437
        if (certfile)
 
438
                /* Note: this call can generate memory leaks not resolvable
 
439
                 * by any release function.
 
440
                 * Probably NSS key module object allocation and
 
441
                 * probably NSS key db object allocation too. */
 
442
                status = NSS_Init(certfile);
 
443
        else
 
444
                status = NSS_NoDB_Init(NULL);
 
445
        if (status != SECSuccess) {
 
446
                upslogx(LOG_ERR, "Can not initialize SSL context");
 
447
                nss_error("upscli_init / NSS_[NoDB]_Init");     
 
448
                return;
 
449
        }
 
450
        
 
451
        status = NSS_SetDomesticPolicy();
 
452
        if (status != SECSuccess) {
 
453
                upslogx(LOG_ERR, "Can not initialize SSL policy");
 
454
                nss_error("upscli_init / NSS_SetDomesticPolicy");
 
455
                return;
 
456
        }
 
457
 
 
458
        /* Default server cache config */
 
459
        status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
 
460
        if (status != SECSuccess) {
 
461
                upslogx(LOG_ERR, "Can not initialize SSL server cache");
 
462
                nss_error("upscli_init / SSL_ConfigServerSessionIDCache");
 
463
                return;
 
464
        }
 
465
        
 
466
        status = SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_TRUE);
 
467
        if (status != SECSuccess) {
 
468
                upslogx(LOG_ERR, "Can not enable SSLv3");
 
469
                nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_SSL3)");
 
470
                return;
 
471
        }
 
472
        status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
 
473
        if (status != SECSuccess) {
 
474
                upslogx(LOG_ERR, "Can not enable TLSv1");
 
475
                nss_error("upscli_init / SSL_OptionSetDefault(SSL_ENABLE_TLS)");
 
476
                return;
 
477
        }
 
478
 
 
479
#ifdef WITH_CLIENT_CERTIFICATE_VALIDATION
 
480
        if (certrequest < NETSSL_CERTREQ_NO &&
 
481
                certrequest > NETSSL_CERTREQ_REQUEST) {
 
482
                upslogx(LOG_ERR, "Invalid certificate requirement");
 
483
                return;
 
484
        }
 
485
 
 
486
        if (certrequest == NETSSL_CERTREQ_REQUEST || 
 
487
                certrequest == NETSSL_CERTREQ_REQUIRE ) {
 
488
                status = SSL_OptionSetDefault(SSL_REQUEST_CERTIFICATE, PR_TRUE);
 
489
                if (status != SECSuccess) {
 
490
                        upslogx(LOG_ERR, "Can not enable certificate request");
 
491
                        nss_error("upscli_init / SSL_OptionSetDefault(SSL_REQUEST_CERTIFICATE)");
 
492
                        return;
 
493
                }
 
494
        }
 
495
 
 
496
        if (certrequest == NETSSL_CERTREQ_REQUIRE ) {
 
497
                status = SSL_OptionSetDefault(SSL_REQUIRE_CERTIFICATE, PR_TRUE);
 
498
                if (status != SECSuccess) {
 
499
                        upslogx(LOG_ERR, "Can not enable certificate requirement");
 
500
                        nss_error("upscli_init / SSL_OptionSetDefault(SSL_REQUIRE_CERTIFICATE)");
 
501
                        return;
 
502
                }
 
503
        }
 
504
#endif /* WITH_CLIENT_CERTIFICATE_VALIDATION */
 
505
        
 
506
        cert = PK11_FindCertFromNickname(certname, NULL);
 
507
        if(cert==NULL)  {
 
508
                upslogx(LOG_ERR, "Can not find server certificate");
 
509
                nss_error("upscli_init / PK11_FindCertFromNickname");
 
510
                return;
 
511
        }
 
512
        
 
513
        privKey = PK11_FindKeyByAnyCert(cert, NULL);
 
514
        if(privKey==NULL){
 
515
                upslogx(LOG_ERR, "Can not find private key associate to server certificate");
 
516
                nss_error("upscli_init / PK11_FindKeyByAnyCert");
 
517
                return;
 
518
        }
 
519
                
 
520
        ssl_initialized = 1;
 
521
#else /* WITH_OPENSSL | WITH_NSS */
 
522
        upslogx(LOG_ERR, "ssl_init called but SSL wasn't compiled in");
 
523
#endif /* WITH_OPENSSL | WITH_NSS */
 
524
}
 
525
 
 
526
int ssl_read(nut_ctype_t *client, char *buf, size_t buflen)
 
527
{
 
528
        int     ret;
 
529
 
 
530
        if (!client->ssl_connected) {
 
531
                return -1;
 
532
        }
 
533
 
 
534
#ifdef WITH_OPENSSL
 
535
        ret = SSL_read(client->ssl, buf, buflen);
 
536
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
537
        ret = PR_Read(client->ssl, buf, buflen);
 
538
#endif /* WITH_OPENSSL | WITH_NSS */
 
539
 
 
540
        if (ret < 1) {
 
541
                ssl_error(client->ssl, ret);
 
542
                return -1;
 
543
        }
 
544
 
 
545
        return ret;
 
546
}
 
547
 
 
548
int ssl_write(nut_ctype_t *client, const char *buf, size_t buflen)
 
549
{
 
550
        int     ret;
 
551
 
 
552
        if (!client->ssl_connected) {
 
553
                return -1;
 
554
        }
 
555
 
 
556
#ifdef WITH_OPENSSL
 
557
        ret = SSL_write(client->ssl, buf, buflen);
 
558
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
559
        ret = PR_Write(client->ssl, buf, buflen);
 
560
#endif /* WITH_OPENSSL | WITH_NSS */
 
561
 
 
562
        upsdebugx(5, "ssl_write ret=%d", ret);
 
563
 
 
564
        return ret;
 
565
}
 
566
 
 
567
void ssl_finish(nut_ctype_t *client)
 
568
{
 
569
        if (client->ssl) {
 
570
#ifdef WITH_OPENSSL
 
571
                SSL_free(client->ssl);
 
572
#elif defined(WITH_NSS)
 
573
                PR_Shutdown(client->ssl, PR_SHUTDOWN_BOTH);
 
574
                PR_Close(client->ssl);
 
575
#endif /* WITH_OPENSSL | WITH_NSS */
 
576
                client->ssl_connected = 0;
 
577
                client->ssl = NULL;
 
578
        }
 
579
}
 
580
 
 
581
void ssl_cleanup(void)
 
582
{
 
583
#ifdef WITH_OPENSSL
 
584
        if (ssl_ctx) {
 
585
                SSL_CTX_free(ssl_ctx);
 
586
                ssl_ctx = NULL;
 
587
        }
 
588
#elif defined(WITH_NSS) /* WITH_OPENSSL */
 
589
        CERT_DestroyCertificate(cert);
 
590
    SECKEY_DestroyPrivateKey(privKey);
 
591
        NSS_Shutdown();
 
592
        PR_Cleanup();
 
593
        /* Called to release memory arena used by NSS/NSPR.
 
594
         * Prevent to show all PL_ArenaAllocate mem alloc as leaks.
 
595
         * https://developer.mozilla.org/en/NSS_Memory_allocation
 
596
         */
 
597
        PL_ArenaFinish();
 
598
#endif /* WITH_OPENSSL | WITH_NSS */
 
599
        ssl_initialized = 0;
 
600
}
 
601
 
 
602
#endif /* WITH_SSL */