4 * TLS support code for CUPS using GNU TLS.
6 * Copyright 2007-2013 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
23 static int make_certificate(cupsd_client_t
*con
);
27 * 'http_tls_initialize()' - Initialize the TLS stack.
31 http_tls_initialize(void)
35 * Initialize GNU TLS...
40 #elif defined(HAVE_LIBSSL)
42 * Initialize OpenSSL...
45 SSL_load_error_strings();
49 * Using the current time is a dubious random seed, but on some systems
50 * it is the best we can do (on others, this seed isn't even used...)
53 CUPS_SRAND(time(NULL
));
55 for (i
= 0; i
< sizeof(data
); i
++)
56 data
[i
] = CUPS_RAND();
58 RAND_seed(data
, sizeof(data
));
59 #endif /* HAVE_GNUTLS */
65 * 'http_tls_read()' - Read from a SSL/TLS connection.
68 static int /* O - Bytes read */
69 http_tls_read(http_t
*http
, /* I - Connection to server */
70 char *buf
, /* I - Buffer to store data */
71 int len
) /* I - Length of buffer */
73 # if defined(HAVE_LIBSSL)
74 return (SSL_read((SSL
*)(http
->tls
), buf
, len
));
76 # elif defined(HAVE_GNUTLS)
77 ssize_t result
; /* Return value */
80 result
= gnutls_record_recv(http
->tls
, buf
, len
);
82 if (result
< 0 && !errno
)
85 * Convert GNU TLS error to errno value...
90 case GNUTLS_E_INTERRUPTED
:
106 return ((int)result
);
108 # elif defined(HAVE_CDSASSL)
109 int result
; /* Return value */
110 OSStatus error
; /* Error info */
111 size_t processed
; /* Number of bytes processed */
114 error
= SSLRead(http
->tls
, buf
, len
, &processed
);
115 DEBUG_printf(("6http_tls_read: error=%d, processed=%d", (int)error
,
120 result
= (int)processed
;
123 case errSSLWouldBlock
:
125 result
= (int)processed
;
133 case errSSLClosedGraceful
:
136 result
= (int)processed
;
147 # elif defined(HAVE_SSPISSL)
148 return _sspiRead((_sspi_struct_t
*) http
->tls
, buf
, len
);
149 # endif /* HAVE_LIBSSL */
151 #endif /* HAVE_SSL */
156 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
159 static int /* O - 0 on success, -1 on failure */
160 http_setup_ssl(http_t
*http
) /* I - Connection to server */
162 char hostname
[256], /* Hostname */
163 *hostptr
; /* Pointer into hostname */
166 SSL_CTX
*context
; /* Context for encryption */
167 BIO
*bio
; /* BIO data */
168 const char *message
= NULL
;/* Error message */
169 # elif defined(HAVE_GNUTLS)
170 int status
; /* Status of handshake */
171 gnutls_certificate_client_credentials
*credentials
;
172 /* TLS credentials */
173 # elif defined(HAVE_CDSASSL)
174 _cups_globals_t
*cg
= _cupsGlobals();
175 /* Pointer to library globals */
176 OSStatus error
; /* Error code */
177 const char *message
= NULL
;/* Error message */
178 cups_array_t
*credentials
; /* Credentials array */
179 cups_array_t
*names
; /* CUPS distinguished names */
180 CFArrayRef dn_array
; /* CF distinguished names array */
181 CFIndex count
; /* Number of credentials */
182 CFDataRef data
; /* Certificate data */
183 int i
; /* Looping var */
184 http_credential_t
*credential
; /* Credential data */
185 # elif defined(HAVE_SSPISSL)
186 TCHAR username
[256]; /* Username returned from GetUserName() */
187 TCHAR commonName
[256];/* Common name for certificate */
188 DWORD dwSize
; /* 32 bit size */
189 # endif /* HAVE_LIBSSL */
192 DEBUG_printf(("7http_setup_ssl(http=%p)", http
));
195 * Get the hostname to use for SSL...
198 if (httpAddrLocalhost(http
->hostaddr
))
200 strlcpy(hostname
, "localhost", sizeof(hostname
));
205 * Otherwise make sure the hostname we have does not end in a trailing dot.
208 strlcpy(hostname
, http
->hostname
, sizeof(hostname
));
209 if ((hostptr
= hostname
+ strlen(hostname
) - 1) >= hostname
&&
215 context
= SSL_CTX_new(SSLv23_client_method());
217 SSL_CTX_set_options(context
, SSL_OP_NO_SSLv2
); /* Only use SSLv3 or TLS */
219 bio
= BIO_new(_httpBIOMethods());
220 BIO_ctrl(bio
, BIO_C_SET_FILE_PTR
, 0, (char *)http
);
222 http
->tls
= SSL_new(context
);
223 SSL_set_bio(http
->tls
, bio
, bio
);
225 # ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
226 SSL_set_tlsext_host_name(http
->tls
, hostname
);
227 # endif /* HAVE_SSL_SET_TLSEXT_HOST_NAME */
229 if (SSL_connect(http
->tls
) != 1)
231 unsigned long error
; /* Error code */
233 while ((error
= ERR_get_error()) != 0)
235 message
= ERR_error_string(error
, NULL
);
236 DEBUG_printf(("8http_setup_ssl: %s", message
));
239 SSL_CTX_free(context
);
244 http
->error
= WSAGetLastError();
248 http
->status
= HTTP_STATUS_ERROR
;
251 message
= _("Unable to establish a secure connection to host.");
253 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI
, message
, 1);
258 # elif defined(HAVE_GNUTLS)
259 credentials
= (gnutls_certificate_client_credentials
*)
260 malloc(sizeof(gnutls_certificate_client_credentials
));
261 if (credentials
== NULL
)
263 DEBUG_printf(("8http_setup_ssl: Unable to allocate credentials: %s",
266 http
->status
= HTTP_STATUS_ERROR
;
267 _cupsSetHTTPError(HTTP_STATUS_ERROR
);
272 gnutls_certificate_allocate_credentials(credentials
);
274 gnutls_init(&http
->tls
, GNUTLS_CLIENT
);
275 gnutls_set_default_priority(http
->tls
);
276 gnutls_server_name_set(http
->tls
, GNUTLS_NAME_DNS
, hostname
,
278 gnutls_credentials_set(http
->tls
, GNUTLS_CRD_CERTIFICATE
, *credentials
);
279 gnutls_transport_set_ptr(http
->tls
, (gnutls_transport_ptr
)http
);
280 gnutls_transport_set_pull_function(http
->tls
, _httpReadGNUTLS
);
281 gnutls_transport_set_push_function(http
->tls
, _httpWriteGNUTLS
);
283 while ((status
= gnutls_handshake(http
->tls
)) != GNUTLS_E_SUCCESS
)
285 DEBUG_printf(("8http_setup_ssl: gnutls_handshake returned %d (%s)",
286 status
, gnutls_strerror(status
)));
288 if (gnutls_error_is_fatal(status
))
291 http
->status
= HTTP_STATUS_ERROR
;
293 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI
, gnutls_strerror(status
), 0);
295 gnutls_deinit(http
->tls
);
296 gnutls_certificate_free_credentials(*credentials
);
304 http
->tls_credentials
= credentials
;
306 # elif defined(HAVE_CDSASSL)
307 if ((http
->tls
= SSLCreateContext(kCFAllocatorDefault
, kSSLClientSide
,
308 kSSLStreamType
)) == NULL
)
310 DEBUG_puts("4http_setup_ssl: SSLCreateContext failed.");
311 http
->error
= errno
= ENOMEM
;
312 http
->status
= HTTP_STATUS_ERROR
;
313 _cupsSetHTTPError(HTTP_STATUS_ERROR
);
318 error
= SSLSetConnection(http
->tls
, http
);
319 DEBUG_printf(("4http_setup_ssl: SSLSetConnection, error=%d", (int)error
));
323 error
= SSLSetIOFuncs(http
->tls
, _httpReadCDSA
, _httpWriteCDSA
);
324 DEBUG_printf(("4http_setup_ssl: SSLSetIOFuncs, error=%d", (int)error
));
329 error
= SSLSetSessionOption(http
->tls
, kSSLSessionOptionBreakOnServerAuth
,
331 DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d",
337 if (cg
->client_cert_cb
)
339 error
= SSLSetSessionOption(http
->tls
,
340 kSSLSessionOptionBreakOnCertRequested
, true);
341 DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnCertRequested, "
342 "error=%d", (int)error
));
346 error
= http_set_credentials(http
);
347 DEBUG_printf(("4http_setup_ssl: http_set_credentials, error=%d",
353 * Let the server know which hostname/domain we are trying to connect to
354 * in case it wants to serve up a certificate with a matching common name.
359 error
= SSLSetPeerDomainName(http
->tls
, hostname
, strlen(hostname
));
361 DEBUG_printf(("4http_setup_ssl: SSLSetPeerDomainName, error=%d",
367 int done
= 0; /* Are we done yet? */
369 while (!error
&& !done
)
371 error
= SSLHandshake(http
->tls
);
373 DEBUG_printf(("4http_setup_ssl: SSLHandshake returned %d.", (int)error
));
381 case errSSLWouldBlock
:
382 error
= noErr
; /* Force a retry */
383 usleep(1000); /* in 1 millisecond */
386 case errSSLServerAuthCompleted
:
388 if (cg
->server_cert_cb
)
390 error
= httpCopyCredentials(http
, &credentials
);
393 error
= (cg
->server_cert_cb
)(http
, http
->tls
, credentials
,
394 cg
->server_cert_data
);
395 httpFreeCredentials(credentials
);
398 DEBUG_printf(("4http_setup_ssl: Server certificate callback "
399 "returned %d.", (int)error
));
403 case errSSLClientCertRequested
:
406 if (cg
->client_cert_cb
)
409 if (!(error
= SSLCopyDistinguishedNames(http
->tls
, &dn_array
)) &&
412 if ((names
= cupsArrayNew(NULL
, NULL
)) != NULL
)
414 for (i
= 0, count
= CFArrayGetCount(dn_array
); i
< count
; i
++)
416 data
= (CFDataRef
)CFArrayGetValueAtIndex(dn_array
, i
);
418 if ((credential
= malloc(sizeof(*credential
))) != NULL
)
420 credential
->datalen
= CFDataGetLength(data
);
421 if ((credential
->data
= malloc(credential
->datalen
)))
423 memcpy((void *)credential
->data
, CFDataGetBytePtr(data
),
424 credential
->datalen
);
425 cupsArrayAdd(names
, credential
);
438 error
= (cg
->client_cert_cb
)(http
, http
->tls
, names
,
439 cg
->client_cert_data
);
441 DEBUG_printf(("4http_setup_ssl: Client certificate callback "
442 "returned %d.", (int)error
));
445 httpFreeCredentials(names
);
449 case errSSLUnknownRootCert
:
450 message
= _("Unable to establish a secure connection to host "
451 "(untrusted certificate).");
454 case errSSLNoRootCert
:
455 message
= _("Unable to establish a secure connection to host "
456 "(self-signed certificate).");
459 case errSSLCertExpired
:
460 message
= _("Unable to establish a secure connection to host "
461 "(expired certificate).");
464 case errSSLCertNotYetValid
:
465 message
= _("Unable to establish a secure connection to host "
466 "(certificate not yet valid).");
469 case errSSLHostNameMismatch
:
470 message
= _("Unable to establish a secure connection to host "
471 "(host name mismatch).");
474 case errSSLXCertChainInvalid
:
475 message
= _("Unable to establish a secure connection to host "
476 "(certificate chain invalid).");
479 case errSSLConnectionRefused
:
480 message
= _("Unable to establish a secure connection to host "
481 "(peer dropped connection before responding).");
493 http
->status
= HTTP_STATUS_ERROR
;
494 errno
= ECONNREFUSED
;
496 CFRelease(http
->tls
);
500 * If an error string wasn't set by the callbacks use a generic one...
504 #ifdef HAVE_CSSMERRORSTRING
505 message
= cssmErrorString(error
);
507 message
= _("Unable to establish a secure connection to host.");
508 #endif /* HAVE_CSSMERRORSTRING */
510 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI
, message
, 1);
515 # elif defined(HAVE_SSPISSL)
516 http
->tls
= _sspiAlloc();
520 _cupsSetHTTPError(HTTP_STATUS_ERROR
);
524 http
->tls
->sock
= http
->fd
;
525 dwSize
= sizeof(username
) / sizeof(TCHAR
);
526 GetUserName(username
, &dwSize
);
527 _sntprintf_s(commonName
, sizeof(commonName
) / sizeof(TCHAR
),
528 sizeof(commonName
) / sizeof(TCHAR
), TEXT("CN=%s"), username
);
530 if (!_sspiGetCredentials(http
->tls_credentials
, L
"ClientContainer",
533 _sspiFree(http
->tls_credentials
);
534 http
->tls_credentials
= NULL
;
537 http
->status
= HTTP_STATUS_ERROR
;
539 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI
,
540 _("Unable to establish a secure connection to host."), 1);
545 _sspiSetAllowsAnyRoot(http
->tls_credentials
, TRUE
);
546 _sspiSetAllowsExpiredCerts(http
->tls_credentials
, TRUE
);
548 if (!_sspiConnect(http
->tls_credentials
, hostname
))
550 _sspiFree(http
->tls_credentials
);
551 http
->tls_credentials
= NULL
;
554 http
->status
= HTTP_STATUS_ERROR
;
556 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI
,
557 _("Unable to establish a secure connection to host."), 1);
561 # endif /* HAVE_CDSASSL */
568 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
572 http_shutdown_ssl(http_t
*http
) /* I - Connection to server */
575 SSL_CTX
*context
; /* Context for encryption */
577 context
= SSL_get_SSL_CTX(http
->tls
);
579 SSL_shutdown(http
->tls
);
580 SSL_CTX_free(context
);
583 # elif defined(HAVE_GNUTLS)
584 gnutls_certificate_client_credentials
*credentials
;
585 /* TLS credentials */
587 credentials
= (gnutls_certificate_client_credentials
*)(http
->tls_credentials
);
589 gnutls_bye(http
->tls
, GNUTLS_SHUT_RDWR
);
590 gnutls_deinit(http
->tls
);
591 gnutls_certificate_free_credentials(*credentials
);
594 # elif defined(HAVE_CDSASSL)
595 while (SSLClose(http
->tls
) == errSSLWouldBlock
)
598 CFRelease(http
->tls
);
600 if (http
->tls_credentials
)
601 CFRelease(http
->tls_credentials
);
603 # elif defined(HAVE_SSPISSL)
604 _sspiFree(http
->tls_credentials
);
605 # endif /* HAVE_LIBSSL */
608 http
->tls_credentials
= NULL
;
610 #endif /* HAVE_SSL */
615 * 'http_write_ssl()' - Write to a SSL/TLS connection.
618 static int /* O - Bytes written */
619 http_write_ssl(http_t
*http
, /* I - Connection to server */
620 const char *buf
, /* I - Buffer holding data */
621 int len
) /* I - Length of buffer */
623 ssize_t result
; /* Return value */
626 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http
, buf
, len
));
628 # if defined(HAVE_LIBSSL)
629 result
= SSL_write((SSL
*)(http
->tls
), buf
, len
);
631 # elif defined(HAVE_GNUTLS)
632 result
= gnutls_record_send(http
->tls
, buf
, len
);
634 if (result
< 0 && !errno
)
637 * Convert GNU TLS error to errno value...
642 case GNUTLS_E_INTERRUPTED
:
646 case GNUTLS_E_AGAIN
:
658 # elif defined(HAVE_CDSASSL)
659 OSStatus error
; /* Error info */
660 size_t processed
; /* Number of bytes processed */
663 error
= SSLWrite(http
->tls
, buf
, len
, &processed
);
668 result
= (int)processed
;
671 case errSSLWouldBlock
:
673 result
= (int)processed
;
681 case errSSLClosedGraceful
:
684 result
= (int)processed
;
692 # elif defined(HAVE_SSPISSL)
693 return _sspiWrite((_sspi_struct_t
*)http
->tls
, (void *)buf
, len
);
694 # endif /* HAVE_LIBSSL */
696 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result
));
698 return ((int)result
);
700 #endif /* HAVE_SSL */
704 * 'http_tls_pending()' - Return the number of pending TLS-encrypted bytes.
708 http_tls_pending(http_t
*http
) /* I - HTTP connection */
710 if (http
->tls
&& usessl
)
713 if (SSL_pending(http
->tls
))
715 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
719 # elif defined(HAVE_GNUTLS)
720 if (gnutls_record_check_pending(http
->tls
))
722 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
726 # elif defined(HAVE_CDSASSL)
727 size_t bytes
; /* Bytes that are available */
729 if (!SSLGetBufferedReadSize(http
->tls
, &bytes
) &&
732 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
735 # endif /* HAVE_LIBSSL */
739 #if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
741 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
744 ssize_t
/* O - Number of bytes read or -1 on error */
746 gnutls_transport_ptr ptr
, /* I - Connection to server */
747 void *data
, /* I - Buffer */
748 size_t length
) /* I - Number of bytes to read */
750 http_t
*http
; /* HTTP connection */
751 ssize_t bytes
; /* Bytes read */
754 DEBUG_printf(("6_httpReadGNUTLS(ptr=%p, data=%p, length=%d)", ptr
, data
, (int)length
));
756 http
= (http_t
*)ptr
;
761 * Make sure we have data before we read...
764 while (!_httpWait(http
, http
->wait_value
, 0))
766 if (http
->timeout_cb
&& (*http
->timeout_cb
)(http
, http
->timeout_data
))
769 http
->error
= ETIMEDOUT
;
774 bytes
= recv(http
->fd
, data
, length
, 0);
775 DEBUG_printf(("6_httpReadGNUTLS: bytes=%d", (int)bytes
));
778 #endif /* HAVE_SSL && HAVE_GNUTLS */
781 #if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
783 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
786 ssize_t
/* O - Number of bytes written or -1 on error */
788 gnutls_transport_ptr ptr
, /* I - Connection to server */
789 const void *data
, /* I - Data buffer */
790 size_t length
) /* I - Number of bytes to write */
792 ssize_t bytes
; /* Bytes written */
795 DEBUG_printf(("6_httpWriteGNUTLS(ptr=%p, data=%p, length=%d)", ptr
, data
,
798 http_debug_hex("_httpWriteGNUTLS", data
, (int)length
);
801 bytes
= send(((http_t
*)ptr
)->fd
, data
, length
, 0);
802 DEBUG_printf(("_httpWriteGNUTLS: bytes=%d", (int)bytes
));
806 #endif /* HAVE_SSL && HAVE_GNUTLS */
810 * 'cupsdEndTLS()' - Shutdown a secure session with the client.
813 int /* O - 1 on success, 0 on error */
814 cupsdEndTLS(cupsd_client_t
*con
) /* I - Client connection */
816 int error
; /* Error code */
817 gnutls_certificate_server_credentials
*credentials
;
818 /* TLS credentials */
821 credentials
= (gnutls_certificate_server_credentials
*)
822 (con
->http
.tls_credentials
);
824 error
= gnutls_bye(con
->http
.tls
, GNUTLS_SHUT_WR
);
827 case GNUTLS_E_SUCCESS
:
828 cupsdLogMessage(CUPSD_LOG_DEBUG
,
829 "SSL shutdown successful!");
832 cupsdLogMessage(CUPSD_LOG_ERROR
,
833 "SSL shutdown failed: %s", gnutls_strerror(error
));
837 gnutls_deinit(con
->http
.tls
);
838 con
->http
.tls
= NULL
;
840 gnutls_certificate_free_credentials(*credentials
);
848 * 'cupsdStartTLS()' - Start a secure session with the client.
851 int /* O - 1 on success, 0 on error */
852 cupsdStartTLS(cupsd_client_t
*con
) /* I - Client connection */
854 int status
; /* Error code */
855 gnutls_certificate_server_credentials
*credentials
;
856 /* TLS credentials */
859 cupsdLogMessage(CUPSD_LOG_DEBUG
, "[Client %d] Encrypting connection.",
863 * Verify that we have a certificate...
866 if (access(ServerKey
, 0) || access(ServerCertificate
, 0))
869 * Nope, make a self-signed certificate...
872 if (!make_certificate(con
))
877 * Create the SSL object and perform the SSL handshake...
880 credentials
= (gnutls_certificate_server_credentials
*)
881 malloc(sizeof(gnutls_certificate_server_credentials
));
882 if (credentials
== NULL
)
884 cupsdLogMessage(CUPSD_LOG_ERROR
,
885 "Unable to encrypt connection from %s - %s",
886 con
->http
.hostname
, strerror(errno
));
891 gnutls_certificate_allocate_credentials(credentials
);
892 gnutls_certificate_set_x509_key_file(*credentials
, ServerCertificate
,
893 ServerKey
, GNUTLS_X509_FMT_PEM
);
895 gnutls_init(&con
->http
.tls
, GNUTLS_SERVER
);
896 gnutls_set_default_priority(con
->http
.tls
);
898 gnutls_credentials_set(con
->http
.tls
, GNUTLS_CRD_CERTIFICATE
, *credentials
);
899 gnutls_transport_set_ptr(con
->http
.tls
, (gnutls_transport_ptr
)HTTP(con
));
900 gnutls_transport_set_pull_function(con
->http
.tls
, _httpReadGNUTLS
);
901 gnutls_transport_set_push_function(con
->http
.tls
, _httpWriteGNUTLS
);
903 while ((status
= gnutls_handshake(con
->http
.tls
)) != GNUTLS_E_SUCCESS
)
905 if (gnutls_error_is_fatal(status
))
907 cupsdLogMessage(CUPSD_LOG_ERROR
,
908 "Unable to encrypt connection from %s - %s",
909 con
->http
.hostname
, gnutls_strerror(status
));
911 gnutls_deinit(con
->http
.tls
);
912 gnutls_certificate_free_credentials(*credentials
);
913 con
->http
.tls
= NULL
;
919 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Connection from %s now encrypted.",
922 con
->http
.tls_credentials
= credentials
;
928 * 'make_certificate()' - Make a self-signed SSL/TLS certificate.
931 static int /* O - 1 on success, 0 on failure */
932 make_certificate(cupsd_client_t
*con
) /* I - Client connection */
934 gnutls_x509_crt crt
; /* Self-signed certificate */
935 gnutls_x509_privkey key
; /* Encryption key */
936 cups_lang_t
*language
; /* Default language info */
937 cups_file_t
*fp
; /* Key/cert file */
938 unsigned char buffer
[8192]; /* Buffer for x509 data */
939 size_t bytes
; /* Number of bytes of data */
940 unsigned char serial
[4]; /* Serial number buffer */
941 time_t curtime
; /* Current time */
942 int result
; /* Result of GNU TLS calls */
946 * Create the encryption key...
949 cupsdLogMessage(CUPSD_LOG_INFO
, "Generating SSL server key...");
951 gnutls_x509_privkey_init(&key
);
952 gnutls_x509_privkey_generate(key
, GNUTLS_PK_RSA
, 2048, 0);
958 bytes
= sizeof(buffer
);
960 if ((result
= gnutls_x509_privkey_export(key
, GNUTLS_X509_FMT_PEM
,
961 buffer
, &bytes
)) < 0)
963 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to export SSL server key - %s",
964 gnutls_strerror(result
));
965 gnutls_x509_privkey_deinit(key
);
968 else if ((fp
= cupsFileOpen(ServerKey
, "w")) != NULL
)
970 cupsFileWrite(fp
, (char *)buffer
, bytes
);
973 cupsdLogMessage(CUPSD_LOG_INFO
, "Created SSL server key file \"%s\"...",
978 cupsdLogMessage(CUPSD_LOG_ERROR
,
979 "Unable to create SSL server key file \"%s\" - %s",
980 ServerKey
, strerror(errno
));
981 gnutls_x509_privkey_deinit(key
);
986 * Create the self-signed certificate...
989 cupsdLogMessage(CUPSD_LOG_INFO
, "Generating self-signed SSL certificate...");
991 language
= cupsLangDefault();
992 curtime
= time(NULL
);
993 serial
[0] = curtime
>> 24;
994 serial
[1] = curtime
>> 16;
995 serial
[2] = curtime
>> 8;
998 gnutls_x509_crt_init(&crt
);
999 if (strlen(language
->language
) == 5)
1000 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COUNTRY_NAME
, 0,
1001 language
->language
+ 3, 2);
1003 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COUNTRY_NAME
, 0,
1005 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COMMON_NAME
, 0,
1006 ServerName
, strlen(ServerName
));
1007 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_ORGANIZATION_NAME
, 0,
1008 ServerName
, strlen(ServerName
));
1009 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME
,
1011 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME
, 0,
1013 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_LOCALITY_NAME
, 0,
1015 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_PKCS9_EMAIL
, 0,
1016 ServerAdmin
, strlen(ServerAdmin
));
1017 gnutls_x509_crt_set_key(crt
, key
);
1018 gnutls_x509_crt_set_serial(crt
, serial
, sizeof(serial
));
1019 gnutls_x509_crt_set_activation_time(crt
, curtime
);
1020 gnutls_x509_crt_set_expiration_time(crt
, curtime
+ 10 * 365 * 86400);
1021 gnutls_x509_crt_set_ca_status(crt
, 0);
1022 gnutls_x509_crt_set_subject_alternative_name(crt
, GNUTLS_SAN_DNSNAME
,
1024 gnutls_x509_crt_set_key_purpose_oid(crt
, GNUTLS_KP_TLS_WWW_SERVER
, 0);
1025 gnutls_x509_crt_set_key_usage(crt
, GNUTLS_KEY_KEY_ENCIPHERMENT
);
1026 gnutls_x509_crt_set_version(crt
, 3);
1028 bytes
= sizeof(buffer
);
1029 if (gnutls_x509_crt_get_key_id(crt
, 0, buffer
, &bytes
) >= 0)
1030 gnutls_x509_crt_set_subject_key_id(crt
, buffer
, bytes
);
1032 gnutls_x509_crt_sign(crt
, crt
, key
);
1038 bytes
= sizeof(buffer
);
1039 if ((result
= gnutls_x509_crt_export(crt
, GNUTLS_X509_FMT_PEM
,
1040 buffer
, &bytes
)) < 0)
1041 cupsdLogMessage(CUPSD_LOG_ERROR
,
1042 "Unable to export SSL server certificate - %s",
1043 gnutls_strerror(result
));
1044 else if ((fp
= cupsFileOpen(ServerCertificate
, "w")) != NULL
)
1046 cupsFileWrite(fp
, (char *)buffer
, bytes
);
1049 cupsdLogMessage(CUPSD_LOG_INFO
,
1050 "Created SSL server certificate file \"%s\"...",
1054 cupsdLogMessage(CUPSD_LOG_ERROR
,
1055 "Unable to create SSL server certificate file \"%s\" - %s",
1056 ServerCertificate
, strerror(errno
));
1062 gnutls_x509_crt_deinit(crt
);
1063 gnutls_x509_privkey_deinit(key
);