4 * TLS support code for CUPS using GNU TLS.
6 * Copyright 2007-2014 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 tls_auto_create
= 0;
24 /* Auto-create self-signed certs? */
25 static char *tls_common_name
= NULL
;
26 /* Default common name */
27 static char *tls_keypath
= NULL
;
28 /* Server cert keychain path */
29 static _cups_mutex_t tls_mutex
= _CUPS_MUTEX_INITIALIZER
;
30 /* Mutex for keychain/certs */
37 //static int make_certificate(cupsd_client_t *con);
38 static ssize_t
http_gnutls_read(gnutls_transport_ptr_t ptr
, void *data
, size_t length
);
39 static ssize_t
http_gnutls_write(gnutls_transport_ptr_t ptr
, const void *data
, size_t length
);
43 * 'cupsMakeServerCredentials()' - Make a self-signed certificate and private key pair.
48 int /* O - 1 on success, 0 on failure */
49 cupsMakeServerCredentials(
50 const char *path
, /* I - Path to keychain/directory */
51 const char *common_name
, /* I - Common name */
52 int num_alt_names
, /* I - Number of subject alternate names */
53 const char **alt_names
, /* I - Subject Alternate Names */
54 time_t expiration_date
) /* I - Expiration date */
56 gnutls_x509_crt_t crt
; /* Self-signed certificate */
57 gnutls_x509_privkey_t key
; /* Encryption private key */
58 char temp
[1024], /* Temporary directory name */
59 crtfile
[1024], /* Certificate filename */
60 keyfile
[1024]; /* Private key filename */
61 cups_lang_t
*language
; /* Default language info */
62 cups_file_t
*fp
; /* Key/cert file */
63 unsigned char buffer
[8192]; /* Buffer for x509 data */
64 size_t bytes
; /* Number of bytes of data */
65 unsigned char serial
[4]; /* Serial number buffer */
66 time_t curtime
; /* Current time */
67 int result
; /* Result of GNU TLS calls */
70 DEBUG_printf(("cupsMakeServerCredentials(path=\"%s\", common_name=\"%s\", num_alt_names=%d, alt_names=%p, expiration_date=%d)", path
, common_name
, num_alt_names
, alt_names
, (int)expiration_date
));
78 const char *home
= getenv("HOME"); /* HOME environment variable */
81 snprintf(temp
, sizeof(temp
), "%s/.cups/ssl", home
);
83 snprintf(temp
, sizeof(temp
), "%s/ssl", CUPS_SERVERROOT
);
87 DEBUG_printf(("1cupsMakeServerCredentials: Using default path \"%s\".", path
));
90 snprintf(crtfile
, sizeof(crtfile
), "%s/%s.crt", path
, common_name
);
91 snprintf(keyfile
, sizeof(keyfile
), "%s/%s.key", path
, common_name
);
94 * Create the encryption key...
97 gnutls_x509_privkey_init(&key
);
98 gnutls_x509_privkey_generate(key
, GNUTLS_PK_RSA
, 2048, 0);
104 bytes
= sizeof(buffer
);
106 if ((result
= gnutls_x509_privkey_export(key
, GNUTLS_X509_FMT_PEM
,
107 buffer
, &bytes
)) < 0)
109 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, gnutls_strerror(result
), 0);
110 gnutls_x509_privkey_deinit(key
);
113 else if ((fp
= cupsFileOpen(keyfile
, "w")) != NULL
)
115 cupsFileWrite(fp
, (char *)buffer
, bytes
);
120 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(errno
), 0);
121 gnutls_x509_privkey_deinit(key
);
126 * Create the self-signed certificate...
129 DEBUG_puts("1cupsMakeServerCredentials: Generating self-signed SSL certificate.");
131 language
= cupsLangDefault();
132 curtime
= time(NULL
);
133 serial
[0] = curtime
>> 24;
134 serial
[1] = curtime
>> 16;
135 serial
[2] = curtime
>> 8;
138 gnutls_x509_crt_init(&crt
);
139 if (strlen(language
->language
) == 5)
140 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COUNTRY_NAME
, 0,
141 language
->language
+ 3, 2);
143 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COUNTRY_NAME
, 0,
145 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COMMON_NAME
, 0,
146 common_name
, strlen(common_name
));
147 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_ORGANIZATION_NAME
, 0,
148 common_name
, strlen(common_name
));
149 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME
,
151 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME
, 0,
153 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_LOCALITY_NAME
, 0,
155 /* gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0,
156 ServerAdmin, strlen(ServerAdmin));*/
157 gnutls_x509_crt_set_key(crt
, key
);
158 gnutls_x509_crt_set_serial(crt
, serial
, sizeof(serial
));
159 gnutls_x509_crt_set_activation_time(crt
, curtime
);
160 gnutls_x509_crt_set_expiration_time(crt
, curtime
+ 10 * 365 * 86400);
161 gnutls_x509_crt_set_ca_status(crt
, 0);
162 if (num_alt_names
> 0)
163 gnutls_x509_crt_set_subject_alternative_name(crt
, GNUTLS_SAN_DNSNAME
, alt_names
[0]);
164 gnutls_x509_crt_set_key_purpose_oid(crt
, GNUTLS_KP_TLS_WWW_SERVER
, 0);
165 gnutls_x509_crt_set_key_usage(crt
, GNUTLS_KEY_KEY_ENCIPHERMENT
);
166 gnutls_x509_crt_set_version(crt
, 3);
168 bytes
= sizeof(buffer
);
169 if (gnutls_x509_crt_get_key_id(crt
, 0, buffer
, &bytes
) >= 0)
170 gnutls_x509_crt_set_subject_key_id(crt
, buffer
, bytes
);
172 gnutls_x509_crt_sign(crt
, crt
, key
);
178 bytes
= sizeof(buffer
);
179 if ((result
= gnutls_x509_crt_export(crt
, GNUTLS_X509_FMT_PEM
, buffer
, &bytes
)) < 0)
181 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, gnutls_strerror(result
), 0);
182 gnutls_x509_crt_deinit(crt
);
183 gnutls_x509_privkey_deinit(key
);
186 else if ((fp
= cupsFileOpen(crtfile
, "w")) != NULL
)
188 cupsFileWrite(fp
, (char *)buffer
, bytes
);
193 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(errno
), 0);
194 gnutls_x509_crt_deinit(crt
);
195 gnutls_x509_privkey_deinit(key
);
203 gnutls_x509_crt_deinit(crt
);
204 gnutls_x509_privkey_deinit(key
);
211 * 'cupsSetServerCredentials()' - Set the default server credentials.
213 * Note: The server credentials are used by all threads in the running process.
214 * This function is threadsafe.
219 int /* O - 1 on success, 0 on failure */
220 cupsSetServerCredentials(
221 const char *path
, /* I - Path to keychain/directory */
222 const char *common_name
, /* I - Default common name for server */
223 int auto_create
) /* I - 1 = automatically create self-signed certificates */
225 char temp
[1024]; /* Default path buffer */
228 DEBUG_printf(("cupsSetServerCredentials(path=\"%s\", common_name=\"%s\", auto_create=%d)", path
, common_name
, auto_create
));
230 _cupsMutexLock(&tls_mutex
);
237 _cupsStrFree(tls_keypath
);
240 _cupsStrFree(tls_common_name
);
243 * Use defaults as needed...
248 const char *home
= getenv("HOME"); /* HOME environment variable */
250 if (getuid() && home
)
251 snprintf(temp
, sizeof(temp
), "%s/.cups/ssl", home
);
253 snprintf(temp
, sizeof(temp
), "%s/ssl", CUPS_SERVERROOT
);
257 DEBUG_printf(("1cupsSetServerCredentials: Using default path \"%s\".", path
));
261 * Save the new values...
264 tls_keypath
= _cupsStrAlloc(path
);
265 tls_auto_create
= auto_create
;
266 tls_common_name
= _cupsStrAlloc(common_name
);
268 _cupsMutexUnlock(&tls_mutex
);
275 * 'httpCopyCredentials()' - Copy the credentials associated with the peer in
276 * an encrypted connection.
278 * @since CUPS 1.5/OS X 10.7@
281 int /* O - Status of call (0 = success) */
283 http_t
*http
, /* I - Connection to server */
284 cups_array_t
**credentials
) /* O - Array of credentials */
289 if (!http
|| !http
->tls
|| !credentials
)
297 * '_httpCreateCredentials()' - Create credentials in the internal format.
300 http_tls_credentials_t
/* O - Internal credentials */
301 _httpCreateCredentials(
302 cups_array_t
*credentials
) /* I - Array of credentials */
311 * '_httpFreeCredentials()' - Free internal credentials.
315 _httpFreeCredentials(
316 http_tls_credentials_t credentials
) /* I - Internal credentials */
323 * 'http_gnutls_read()' - Read function for the GNU TLS library.
326 static ssize_t
/* O - Number of bytes read or -1 on error */
328 gnutls_transport_ptr_t ptr
, /* I - Connection to server */
329 void *data
, /* I - Buffer */
330 size_t length
) /* I - Number of bytes to read */
332 http_t
*http
; /* HTTP connection */
333 ssize_t bytes
; /* Bytes read */
336 DEBUG_printf(("6http_gnutls_read(ptr=%p, data=%p, length=%d)", ptr
, data
, (int)length
));
338 http
= (http_t
*)ptr
;
343 * Make sure we have data before we read...
346 while (!_httpWait(http
, http
->wait_value
, 0))
348 if (http
->timeout_cb
&& (*http
->timeout_cb
)(http
, http
->timeout_data
))
351 http
->error
= ETIMEDOUT
;
356 bytes
= recv(http
->fd
, data
, length
, 0);
357 DEBUG_printf(("6http_gnutls_read: bytes=%d", (int)bytes
));
363 * 'http_gnutls_write()' - Write function for the GNU TLS library.
366 static ssize_t
/* O - Number of bytes written or -1 on error */
368 gnutls_transport_ptr_t ptr
, /* I - Connection to server */
369 const void *data
, /* I - Data buffer */
370 size_t length
) /* I - Number of bytes to write */
372 ssize_t bytes
; /* Bytes written */
375 DEBUG_printf(("6http_gnutls_write(ptr=%p, data=%p, length=%d)", ptr
, data
,
377 bytes
= send(((http_t
*)ptr
)->fd
, data
, length
, 0);
378 DEBUG_printf(("http_gnutls_write: bytes=%d", (int)bytes
));
385 * '_httpTLSInitialize()' - Initialize the TLS stack.
389 _httpTLSInitialize(void)
392 * Initialize GNU TLS...
395 gnutls_global_init();
400 * '_httpTLSPending()' - Return the number of pending TLS-encrypted bytes.
403 size_t /* O - Bytes available */
404 _httpTLSPending(http_t
*http
) /* I - HTTP connection */
406 return (gnutls_record_check_pending(http
->tls
));
411 * '_httpTLSRead()' - Read from a SSL/TLS connection.
414 int /* O - Bytes read */
415 _httpTLSRead(http_t
*http
, /* I - Connection to server */
416 char *buf
, /* I - Buffer to store data */
417 int len
) /* I - Length of buffer */
419 ssize_t result
; /* Return value */
422 result
= gnutls_record_recv(http
->tls
, buf
, (size_t)len
);
424 if (result
< 0 && !errno
)
427 * Convert GNU TLS error to errno value...
432 case GNUTLS_E_INTERRUPTED
:
436 case GNUTLS_E_AGAIN
:
448 return ((int)result
);
453 * '_httpTLSSetCredentials()' - Set the TLS credentials.
456 int /* O - Status of connection */
457 _httpTLSSetCredentials(http_t
*http
) /* I - Connection to server */
466 * '_httpTLSStart()' - Set up SSL/TLS support on a connection.
469 int /* O - 0 on success, -1 on failure */
470 _httpTLSStart(http_t
*http
) /* I - Connection to server */
472 char hostname
[256], /* Hostname */
473 *hostptr
; /* Pointer into hostname */
474 int status
; /* Status of handshake */
475 gnutls_certificate_credentials_t
*credentials
;
476 /* TLS credentials */
479 DEBUG_printf(("7_httpTLSStart(http=%p)", http
));
481 if (http
->mode
== _HTTP_MODE_SERVER
&& !tls_keypath
)
483 DEBUG_puts("4_httpTLSStart: cupsSetServerCredentials not called.");
484 http
->error
= errno
= EINVAL
;
485 http
->status
= HTTP_STATUS_ERROR
;
486 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Server credentials not set."), 1);
491 credentials
= (gnutls_certificate_credentials_t
*)
492 malloc(sizeof(gnutls_certificate_credentials_t
));
493 if (credentials
== NULL
)
495 DEBUG_printf(("8_httpStartTLS: Unable to allocate credentials: %s",
498 http
->status
= HTTP_STATUS_ERROR
;
499 _cupsSetHTTPError(HTTP_STATUS_ERROR
);
504 gnutls_certificate_allocate_credentials(credentials
);
505 gnutls_init(&http
->tls
, http
->mode
== _HTTP_MODE_CLIENT
? GNUTLS_CLIENT
: GNUTLS_SERVER
);
506 gnutls_set_default_priority(http
->tls
);
507 gnutls_transport_set_ptr(http
->tls
, (gnutls_transport_ptr_t
)http
);
508 gnutls_transport_set_pull_function(http
->tls
, http_gnutls_read
);
509 gnutls_transport_set_push_function(http
->tls
, http_gnutls_write
);
511 if (http
->mode
== _HTTP_MODE_CLIENT
)
514 * Client: get the hostname to use for TLS...
517 if (httpAddrLocalhost(http
->hostaddr
))
519 strlcpy(hostname
, "localhost", sizeof(hostname
));
524 * Otherwise make sure the hostname we have does not end in a trailing dot.
527 strlcpy(hostname
, http
->hostname
, sizeof(hostname
));
528 if ((hostptr
= hostname
+ strlen(hostname
) - 1) >= hostname
&&
533 gnutls_server_name_set(http
->tls
, GNUTLS_NAME_DNS
, hostname
, strlen(hostname
));
534 gnutls_credentials_set(http
->tls
, GNUTLS_CRD_CERTIFICATE
, *credentials
);
539 * Server: get certificate and private key...
542 char crtfile
[1024], /* Certificate file */
543 keyfile
[1024]; /* Private key file */
544 int have_creds
= 0; /* Have credentials? */
547 if (http
->fields
[HTTP_FIELD_HOST
][0])
550 * Use hostname for TLS upgrade...
553 strlcpy(hostname
, http
->fields
[HTTP_FIELD_HOST
], sizeof(hostname
));
558 * Resolve hostname from connection address...
561 http_addr_t addr
; /* Connection address */
562 socklen_t addrlen
; /* Length of address */
564 addrlen
= sizeof(addr
);
565 if (getsockname(http
->fd
, (struct sockaddr
*)&addr
, &addrlen
))
567 DEBUG_printf(("4_httpTLSStart: Unable to get socket address: %s", strerror(errno
)));
570 else if (httpAddrLocalhost(&addr
))
574 httpAddrLookup(&addr
, hostname
, sizeof(hostname
));
575 DEBUG_printf(("4_httpTLSStart: Resolved socket address to \"%s\".", hostname
));
579 if (isdigit(hostname
[0] & 255) || hostname
[0] == '[')
580 hostname
[0] = '\0'; /* Don't allow numeric addresses */
584 snprintf(crtfile
, sizeof(crtfile
), "%s/%s.crt", tls_keypath
, hostname
);
585 snprintf(keyfile
, sizeof(keyfile
), "%s/%s.key", tls_keypath
, hostname
);
587 have_creds
= !access(crtfile
, 0) && !access(keyfile
, 0);
589 else if (tls_common_name
)
591 snprintf(crtfile
, sizeof(crtfile
), "%s/%s.crt", tls_keypath
, tls_common_name
);
592 snprintf(keyfile
, sizeof(keyfile
), "%s/%s.key", tls_keypath
, tls_common_name
);
594 have_creds
= !access(crtfile
, 0) && !access(keyfile
, 0);
597 if (!have_creds
&& tls_auto_create
&& (hostname
[0] || tls_common_name
))
599 DEBUG_printf(("4_httpTLSStart: Auto-create credentials for \"%s\".", hostname
[0] ? hostname
: tls_common_name
));
601 if (!cupsMakeServerCredentials(tls_keypath
, hostname
[0] ? hostname
: tls_common_name
, 0, NULL
, time(NULL
) + 365 * 86400))
603 DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed.");
604 http
->error
= errno
= EINVAL
;
605 http
->status
= HTTP_STATUS_ERROR
;
606 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Unable to create server credentials."), 1);
612 gnutls_certificate_set_x509_key_file(*credentials
, crtfile
, keyfile
, GNUTLS_X509_FMT_PEM
);
615 while ((status
= gnutls_handshake(http
->tls
)) != GNUTLS_E_SUCCESS
)
617 DEBUG_printf(("8_httpStartTLS: gnutls_handshake returned %d (%s)",
618 status
, gnutls_strerror(status
)));
620 if (gnutls_error_is_fatal(status
))
623 http
->status
= HTTP_STATUS_ERROR
;
625 _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI
, gnutls_strerror(status
), 0);
627 gnutls_deinit(http
->tls
);
628 gnutls_certificate_free_credentials(*credentials
);
636 http
->tls_credentials
= credentials
;
638 // TODO: Put this in the right place; no-op for now, this to get things to compile
639 // http_tls_set_credentials(http);
646 * '_httpTLSStop()' - Shut down SSL/TLS on a connection.
650 _httpTLSStop(http_t
*http
) /* I - Connection to server */
652 int error
; /* Error code */
655 error
= gnutls_bye(http
->tls
, http
->mode
== _HTTP_MODE_CLIENT
? GNUTLS_SHUT_RDWR
: GNUTLS_SHUT_WR
);
656 if (error
!= GNUTLS_E_SUCCESS
)
657 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, gnutls_strerror(errno
), 0);
659 gnutls_deinit(http
->tls
);
662 gnutls_certificate_free_credentials(*(http
->tls_credentials
));
663 free(http
->tls_credentials
);
664 http
->tls_credentials
= NULL
;
669 * '_httpTLSWrite()' - Write to a SSL/TLS connection.
672 int /* O - Bytes written */
673 _httpTLSWrite(http_t
*http
, /* I - Connection to server */
674 const char *buf
, /* I - Buffer holding data */
675 int len
) /* I - Length of buffer */
677 ssize_t result
; /* Return value */
680 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http
, buf
, len
));
682 result
= gnutls_record_send(http
->tls
, buf
, (size_t)len
);
684 if (result
< 0 && !errno
)
687 * Convert GNU TLS error to errno value...
692 case GNUTLS_E_INTERRUPTED
:
696 case GNUTLS_E_AGAIN
:
708 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result
));
710 return ((int)result
);
716 * 'cupsdEndTLS()' - Shutdown a secure session with the client.
719 int /* O - 1 on success, 0 on error */
720 cupsdEndTLS(cupsd_client_t
*con
) /* I - Client connection */
722 int error
; /* Error code */
723 gnutls_certificate_server_credentials
*credentials
;
724 /* TLS credentials */
727 credentials
= (gnutls_certificate_server_credentials
*)
728 (con
->http
.tls_credentials
);
730 error
= gnutls_bye(con
->http
.tls
, GNUTLS_SHUT_WR
);
733 case GNUTLS_E_SUCCESS
:
734 cupsdLogMessage(CUPSD_LOG_DEBUG
,
735 "SSL shutdown successful!");
738 cupsdLogMessage(CUPSD_LOG_ERROR
,
739 "SSL shutdown failed: %s", gnutls_strerror(error
));
743 gnutls_deinit(con
->http
.tls
);
744 con
->http
.tls
= NULL
;
746 gnutls_certificate_free_credentials(*credentials
);
754 * 'cupsdStartTLS()' - Start a secure session with the client.
757 int /* O - 1 on success, 0 on error */
758 cupsdStartTLS(cupsd_client_t
*con
) /* I - Client connection */
760 int status
; /* Error code */
761 gnutls_certificate_credentials_t
*credentials
;
762 /* TLS credentials */
765 cupsdLogMessage(CUPSD_LOG_DEBUG
, "[Client %d] Encrypting connection.",
769 * Verify that we have a certificate...
772 if (access(ServerKey
, 0) || access(ServerCertificate
, 0))
775 * Nope, make a self-signed certificate...
778 if (!make_certificate(con
))
783 * Create the SSL object and perform the SSL handshake...
786 credentials
= (gnutls_certificate_credentials_t
*)
787 malloc(sizeof(gnutls_certificate_credentials_t
));
788 if (credentials
== NULL
)
790 cupsdLogMessage(CUPSD_LOG_ERROR
,
791 "Unable to encrypt connection from %s - %s",
792 con
->http
.hostname
, strerror(errno
));
797 gnutls_certificate_allocate_credentials(credentials
);
798 gnutls_certificate_set_x509_key_file(*credentials
, ServerCertificate
,
799 ServerKey
, GNUTLS_X509_FMT_PEM
);
801 gnutls_init(&con
->http
.tls
, GNUTLS_SERVER
);
802 gnutls_set_default_priority(con
->http
.tls
);
804 gnutls_credentials_set(con
->http
.tls
, GNUTLS_CRD_CERTIFICATE
, *credentials
);
805 gnutls_transport_set_ptr(con
->http
.tls
, (gnutls_transport_ptr_t
)HTTP(con
));
806 gnutls_transport_set_pull_function(con
->http
.tls
, http_gnutls_read
);
807 gnutls_transport_set_push_function(con
->http
.tls
, http_gnutls_write
);
809 while ((status
= gnutls_handshake(con
->http
.tls
)) != GNUTLS_E_SUCCESS
)
811 if (gnutls_error_is_fatal(status
))
813 cupsdLogMessage(CUPSD_LOG_ERROR
,
814 "Unable to encrypt connection from %s - %s",
815 con
->http
.hostname
, gnutls_strerror(status
));
817 gnutls_deinit(con
->http
.tls
);
818 gnutls_certificate_free_credentials(*credentials
);
819 con
->http
.tls
= NULL
;
825 cupsdLogMessage(CUPSD_LOG_DEBUG
, "Connection from %s now encrypted.",
828 con
->http
.tls_credentials
= credentials
;
834 * 'make_certificate()' - Make a self-signed SSL/TLS certificate.
837 static int /* O - 1 on success, 0 on failure */
838 make_certificate(cupsd_client_t
*con
) /* I - Client connection */
840 gnutls_x509_crt crt
; /* Self-signed certificate */
841 gnutls_x509_privkey key
; /* Encryption key */
842 cups_lang_t
*language
; /* Default language info */
843 cups_file_t
*fp
; /* Key/cert file */
844 unsigned char buffer
[8192]; /* Buffer for x509 data */
845 size_t bytes
; /* Number of bytes of data */
846 unsigned char serial
[4]; /* Serial number buffer */
847 time_t curtime
; /* Current time */
848 int result
; /* Result of GNU TLS calls */
852 * Create the encryption key...
855 cupsdLogMessage(CUPSD_LOG_INFO
, "Generating SSL server key...");
857 gnutls_x509_privkey_init(&key
);
858 gnutls_x509_privkey_generate(key
, GNUTLS_PK_RSA
, 2048, 0);
864 bytes
= sizeof(buffer
);
866 if ((result
= gnutls_x509_privkey_export(key
, GNUTLS_X509_FMT_PEM
,
867 buffer
, &bytes
)) < 0)
869 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to export SSL server key - %s",
870 gnutls_strerror(result
));
871 gnutls_x509_privkey_deinit(key
);
874 else if ((fp
= cupsFileOpen(ServerKey
, "w")) != NULL
)
876 cupsFileWrite(fp
, (char *)buffer
, bytes
);
879 cupsdLogMessage(CUPSD_LOG_INFO
, "Created SSL server key file \"%s\"...",
884 cupsdLogMessage(CUPSD_LOG_ERROR
,
885 "Unable to create SSL server key file \"%s\" - %s",
886 ServerKey
, strerror(errno
));
887 gnutls_x509_privkey_deinit(key
);
892 * Create the self-signed certificate...
895 cupsdLogMessage(CUPSD_LOG_INFO
, "Generating self-signed SSL certificate...");
897 language
= cupsLangDefault();
898 curtime
= time(NULL
);
899 serial
[0] = curtime
>> 24;
900 serial
[1] = curtime
>> 16;
901 serial
[2] = curtime
>> 8;
904 gnutls_x509_crt_init(&crt
);
905 if (strlen(language
->language
) == 5)
906 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COUNTRY_NAME
, 0,
907 language
->language
+ 3, 2);
909 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COUNTRY_NAME
, 0,
911 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_COMMON_NAME
, 0,
912 ServerName
, strlen(ServerName
));
913 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_ORGANIZATION_NAME
, 0,
914 ServerName
, strlen(ServerName
));
915 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME
,
917 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME
, 0,
919 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_X520_LOCALITY_NAME
, 0,
921 gnutls_x509_crt_set_dn_by_oid(crt
, GNUTLS_OID_PKCS9_EMAIL
, 0,
922 ServerAdmin
, strlen(ServerAdmin
));
923 gnutls_x509_crt_set_key(crt
, key
);
924 gnutls_x509_crt_set_serial(crt
, serial
, sizeof(serial
));
925 gnutls_x509_crt_set_activation_time(crt
, curtime
);
926 gnutls_x509_crt_set_expiration_time(crt
, curtime
+ 10 * 365 * 86400);
927 gnutls_x509_crt_set_ca_status(crt
, 0);
928 gnutls_x509_crt_set_subject_alternative_name(crt
, GNUTLS_SAN_DNSNAME
,
930 gnutls_x509_crt_set_key_purpose_oid(crt
, GNUTLS_KP_TLS_WWW_SERVER
, 0);
931 gnutls_x509_crt_set_key_usage(crt
, GNUTLS_KEY_KEY_ENCIPHERMENT
);
932 gnutls_x509_crt_set_version(crt
, 3);
934 bytes
= sizeof(buffer
);
935 if (gnutls_x509_crt_get_key_id(crt
, 0, buffer
, &bytes
) >= 0)
936 gnutls_x509_crt_set_subject_key_id(crt
, buffer
, bytes
);
938 gnutls_x509_crt_sign(crt
, crt
, key
);
944 bytes
= sizeof(buffer
);
945 if ((result
= gnutls_x509_crt_export(crt
, GNUTLS_X509_FMT_PEM
,
946 buffer
, &bytes
)) < 0)
947 cupsdLogMessage(CUPSD_LOG_ERROR
,
948 "Unable to export SSL server certificate - %s",
949 gnutls_strerror(result
));
950 else if ((fp
= cupsFileOpen(ServerCertificate
, "w")) != NULL
)
952 cupsFileWrite(fp
, (char *)buffer
, bytes
);
955 cupsdLogMessage(CUPSD_LOG_INFO
,
956 "Created SSL server certificate file \"%s\"...",
960 cupsdLogMessage(CUPSD_LOG_ERROR
,
961 "Unable to create SSL server certificate file \"%s\" - %s",
962 ServerCertificate
, strerror(errno
));
968 gnutls_x509_crt_deinit(crt
);
969 gnutls_x509_privkey_deinit(key
);