]>
Commit | Line | Data |
---|---|---|
2c85b752 MS |
1 | /* |
2 | * "$Id$" | |
3 | * | |
4 | * TLS support code for CUPS using GNU TLS. | |
5 | * | |
6 | * Copyright 2007-2013 by Apple Inc. | |
7 | * Copyright 1997-2007 by Easy Software Products, all rights reserved. | |
8 | * | |
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/". | |
14 | * | |
15 | * This file is subject to the Apple OS-Developed Software exception. | |
16 | */ | |
17 | ||
18 | ||
19 | /* | |
20 | * Local functions... | |
21 | */ | |
22 | ||
dd332638 MS |
23 | //static int make_certificate(cupsd_client_t *con); |
24 | static ssize_t http_gnutls_read(gnutls_transport_ptr_t ptr, void *data, size_t length); | |
25 | static ssize_t http_gnutls_write(gnutls_transport_ptr_t ptr, const void *data, size_t length); | |
26 | ||
27 | ||
28 | /* | |
29 | * 'httpCopyCredentials()' - Copy the credentials associated with the peer in | |
30 | * an encrypted connection. | |
31 | * | |
32 | * @since CUPS 1.5/OS X 10.7@ | |
33 | */ | |
34 | ||
35 | int /* O - Status of call (0 = success) */ | |
36 | httpCopyCredentials( | |
37 | http_t *http, /* I - Connection to server */ | |
38 | cups_array_t **credentials) /* O - Array of credentials */ | |
39 | { | |
40 | if (credentials) | |
41 | *credentials = NULL; | |
42 | ||
43 | if (!http || !http->tls || !credentials) | |
44 | return (-1); | |
45 | ||
46 | return (0); | |
47 | } | |
48 | ||
49 | ||
50 | /* | |
51 | * '_httpCreateCredentials()' - Create credentials in the internal format. | |
52 | */ | |
53 | ||
54 | http_tls_credentials_t /* O - Internal credentials */ | |
55 | _httpCreateCredentials( | |
56 | cups_array_t *credentials) /* I - Array of credentials */ | |
57 | { | |
58 | (void)credentials; | |
59 | ||
60 | return (NULL); | |
61 | } | |
62 | ||
63 | ||
64 | /* | |
65 | * '_httpFreeCredentials()' - Free internal credentials. | |
66 | */ | |
67 | ||
68 | void | |
69 | _httpFreeCredentials( | |
70 | http_tls_credentials_t credentials) /* I - Internal credentials */ | |
71 | { | |
72 | (void)credentials; | |
73 | } | |
74 | ||
75 | ||
76 | /* | |
77 | * 'http_gnutls_read()' - Read function for the GNU TLS library. | |
78 | */ | |
79 | ||
80 | static ssize_t /* O - Number of bytes read or -1 on error */ | |
81 | http_gnutls_read( | |
82 | gnutls_transport_ptr_t ptr, /* I - Connection to server */ | |
83 | void *data, /* I - Buffer */ | |
84 | size_t length) /* I - Number of bytes to read */ | |
85 | { | |
86 | http_t *http; /* HTTP connection */ | |
87 | ssize_t bytes; /* Bytes read */ | |
88 | ||
89 | ||
90 | DEBUG_printf(("6http_gnutls_read(ptr=%p, data=%p, length=%d)", ptr, data, (int)length)); | |
91 | ||
92 | http = (http_t *)ptr; | |
93 | ||
94 | if (!http->blocking) | |
95 | { | |
96 | /* | |
97 | * Make sure we have data before we read... | |
98 | */ | |
99 | ||
100 | while (!_httpWait(http, http->wait_value, 0)) | |
101 | { | |
102 | if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data)) | |
103 | continue; | |
104 | ||
105 | http->error = ETIMEDOUT; | |
106 | return (-1); | |
107 | } | |
108 | } | |
109 | ||
110 | bytes = recv(http->fd, data, length, 0); | |
111 | DEBUG_printf(("6http_gnutls_read: bytes=%d", (int)bytes)); | |
112 | return (bytes); | |
113 | } | |
114 | ||
115 | ||
116 | /* | |
117 | * 'http_gnutls_write()' - Write function for the GNU TLS library. | |
118 | */ | |
119 | ||
120 | static ssize_t /* O - Number of bytes written or -1 on error */ | |
121 | http_gnutls_write( | |
122 | gnutls_transport_ptr_t ptr, /* I - Connection to server */ | |
123 | const void *data, /* I - Data buffer */ | |
124 | size_t length) /* I - Number of bytes to write */ | |
125 | { | |
126 | ssize_t bytes; /* Bytes written */ | |
127 | ||
128 | ||
129 | DEBUG_printf(("6http_gnutls_write(ptr=%p, data=%p, length=%d)", ptr, data, | |
130 | (int)length)); | |
131 | #ifdef DEBUG | |
132 | http_debug_hex("http_gnutls_write", data, (int)length); | |
133 | #endif /* DEBUG */ | |
134 | ||
135 | bytes = send(((http_t *)ptr)->fd, data, length, 0); | |
136 | DEBUG_printf(("http_gnutls_write: bytes=%d", (int)bytes)); | |
137 | ||
138 | return (bytes); | |
139 | } | |
2c85b752 MS |
140 | |
141 | ||
142 | /* | |
143 | * 'http_tls_initialize()' - Initialize the TLS stack. | |
144 | */ | |
145 | ||
146 | static void | |
147 | http_tls_initialize(void) | |
148 | { | |
2c85b752 MS |
149 | /* |
150 | * Initialize GNU TLS... | |
151 | */ | |
152 | ||
153 | gnutls_global_init(); | |
dd332638 | 154 | } |
2c85b752 | 155 | |
2c85b752 | 156 | |
dd332638 MS |
157 | /* |
158 | * 'http_tls_pending()' - Return the number of pending TLS-encrypted bytes. | |
159 | */ | |
2c85b752 | 160 | |
dd332638 MS |
161 | static size_t |
162 | http_tls_pending(http_t *http) /* I - HTTP connection */ | |
163 | { | |
164 | return (gnutls_record_check_pending(http->tls)); | |
2c85b752 MS |
165 | } |
166 | ||
167 | ||
2c85b752 MS |
168 | /* |
169 | * 'http_tls_read()' - Read from a SSL/TLS connection. | |
170 | */ | |
171 | ||
172 | static int /* O - Bytes read */ | |
173 | http_tls_read(http_t *http, /* I - Connection to server */ | |
174 | char *buf, /* I - Buffer to store data */ | |
175 | int len) /* I - Length of buffer */ | |
176 | { | |
2c85b752 MS |
177 | ssize_t result; /* Return value */ |
178 | ||
179 | ||
180 | result = gnutls_record_recv(http->tls, buf, len); | |
181 | ||
182 | if (result < 0 && !errno) | |
183 | { | |
184 | /* | |
185 | * Convert GNU TLS error to errno value... | |
186 | */ | |
187 | ||
188 | switch (result) | |
189 | { | |
190 | case GNUTLS_E_INTERRUPTED : | |
191 | errno = EINTR; | |
192 | break; | |
193 | ||
194 | case GNUTLS_E_AGAIN : | |
195 | errno = EAGAIN; | |
196 | break; | |
197 | ||
198 | default : | |
199 | errno = EPIPE; | |
200 | break; | |
201 | } | |
202 | ||
203 | result = -1; | |
204 | } | |
205 | ||
206 | return ((int)result); | |
dd332638 | 207 | } |
2c85b752 MS |
208 | |
209 | ||
dd332638 MS |
210 | /* |
211 | * 'http_tls_set_credentials()' - Set the TLS credentials. | |
212 | */ | |
2c85b752 | 213 | |
dd332638 MS |
214 | static int /* O - Status of connection */ |
215 | http_tls_set_credentials(http_t *http) /* I - Connection to server */ | |
216 | { | |
217 | (void)http; | |
2c85b752 | 218 | |
dd332638 | 219 | return (0); |
2c85b752 | 220 | } |
2c85b752 MS |
221 | |
222 | ||
2c85b752 | 223 | /* |
dd332638 | 224 | * 'http_tls_start()' - Set up SSL/TLS support on a connection. |
2c85b752 MS |
225 | */ |
226 | ||
227 | static int /* O - 0 on success, -1 on failure */ | |
dd332638 | 228 | http_tls_start(http_t *http) /* I - Connection to server */ |
2c85b752 MS |
229 | { |
230 | char hostname[256], /* Hostname */ | |
231 | *hostptr; /* Pointer into hostname */ | |
2c85b752 MS |
232 | int status; /* Status of handshake */ |
233 | gnutls_certificate_client_credentials *credentials; | |
234 | /* TLS credentials */ | |
2c85b752 MS |
235 | |
236 | ||
237 | DEBUG_printf(("7http_setup_ssl(http=%p)", http)); | |
238 | ||
239 | /* | |
240 | * Get the hostname to use for SSL... | |
241 | */ | |
242 | ||
243 | if (httpAddrLocalhost(http->hostaddr)) | |
244 | { | |
245 | strlcpy(hostname, "localhost", sizeof(hostname)); | |
246 | } | |
247 | else | |
248 | { | |
249 | /* | |
250 | * Otherwise make sure the hostname we have does not end in a trailing dot. | |
251 | */ | |
252 | ||
253 | strlcpy(hostname, http->hostname, sizeof(hostname)); | |
254 | if ((hostptr = hostname + strlen(hostname) - 1) >= hostname && | |
255 | *hostptr == '.') | |
256 | *hostptr = '\0'; | |
257 | } | |
258 | ||
2c85b752 MS |
259 | credentials = (gnutls_certificate_client_credentials *) |
260 | malloc(sizeof(gnutls_certificate_client_credentials)); | |
261 | if (credentials == NULL) | |
262 | { | |
263 | DEBUG_printf(("8http_setup_ssl: Unable to allocate credentials: %s", | |
264 | strerror(errno))); | |
265 | http->error = errno; | |
266 | http->status = HTTP_STATUS_ERROR; | |
267 | _cupsSetHTTPError(HTTP_STATUS_ERROR); | |
268 | ||
269 | return (-1); | |
270 | } | |
271 | ||
272 | gnutls_certificate_allocate_credentials(credentials); | |
273 | ||
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, | |
277 | strlen(hostname)); | |
278 | gnutls_credentials_set(http->tls, GNUTLS_CRD_CERTIFICATE, *credentials); | |
dd332638 MS |
279 | gnutls_transport_set_ptr(http->tls, (gnutls_transport_ptr_t)http); |
280 | gnutls_transport_set_pull_function(http->tls, http_gnutls_read); | |
281 | gnutls_transport_set_push_function(http->tls, http_gnutls_write); | |
2c85b752 MS |
282 | |
283 | while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS) | |
284 | { | |
285 | DEBUG_printf(("8http_setup_ssl: gnutls_handshake returned %d (%s)", | |
286 | status, gnutls_strerror(status))); | |
287 | ||
288 | if (gnutls_error_is_fatal(status)) | |
289 | { | |
290 | http->error = EIO; | |
291 | http->status = HTTP_STATUS_ERROR; | |
292 | ||
293 | _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, gnutls_strerror(status), 0); | |
294 | ||
295 | gnutls_deinit(http->tls); | |
296 | gnutls_certificate_free_credentials(*credentials); | |
297 | free(credentials); | |
298 | http->tls = NULL; | |
299 | ||
300 | return (-1); | |
301 | } | |
302 | } | |
303 | ||
304 | http->tls_credentials = credentials; | |
305 | ||
dd332638 MS |
306 | // TODO: Put this in the right place; no-op for now, this to get things to compile |
307 | http_tls_set_credentials(http); | |
2c85b752 MS |
308 | |
309 | return (0); | |
310 | } | |
311 | ||
312 | ||
313 | /* | |
dd332638 | 314 | * 'http_tls_stop()' - Shut down SSL/TLS on a connection. |
2c85b752 MS |
315 | */ |
316 | ||
317 | static void | |
dd332638 | 318 | http_tls_stop(http_t *http) /* I - Connection to server */ |
2c85b752 | 319 | { |
2c85b752 MS |
320 | gnutls_certificate_client_credentials *credentials; |
321 | /* TLS credentials */ | |
322 | ||
323 | credentials = (gnutls_certificate_client_credentials *)(http->tls_credentials); | |
324 | ||
325 | gnutls_bye(http->tls, GNUTLS_SHUT_RDWR); | |
326 | gnutls_deinit(http->tls); | |
327 | gnutls_certificate_free_credentials(*credentials); | |
328 | free(credentials); | |
2c85b752 | 329 | } |
2c85b752 MS |
330 | |
331 | ||
2c85b752 | 332 | /* |
dd332638 | 333 | * 'http_tls_write()' - Write to a SSL/TLS connection. |
2c85b752 MS |
334 | */ |
335 | ||
336 | static int /* O - Bytes written */ | |
dd332638 | 337 | http_tls_write(http_t *http, /* I - Connection to server */ |
2c85b752 MS |
338 | const char *buf, /* I - Buffer holding data */ |
339 | int len) /* I - Length of buffer */ | |
340 | { | |
341 | ssize_t result; /* Return value */ | |
342 | ||
343 | ||
344 | DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len)); | |
345 | ||
2c85b752 MS |
346 | result = gnutls_record_send(http->tls, buf, len); |
347 | ||
348 | if (result < 0 && !errno) | |
349 | { | |
350 | /* | |
351 | * Convert GNU TLS error to errno value... | |
352 | */ | |
353 | ||
354 | switch (result) | |
355 | { | |
356 | case GNUTLS_E_INTERRUPTED : | |
357 | errno = EINTR; | |
358 | break; | |
359 | ||
360 | case GNUTLS_E_AGAIN : | |
361 | errno = EAGAIN; | |
362 | break; | |
363 | ||
364 | default : | |
365 | errno = EPIPE; | |
366 | break; | |
367 | } | |
368 | ||
369 | result = -1; | |
370 | } | |
371 | ||
2c85b752 MS |
372 | DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result)); |
373 | ||
374 | return ((int)result); | |
375 | } | |
2c85b752 MS |
376 | |
377 | ||
dd332638 | 378 | #if 0 |
2c85b752 MS |
379 | /* |
380 | * 'cupsdEndTLS()' - Shutdown a secure session with the client. | |
381 | */ | |
382 | ||
383 | int /* O - 1 on success, 0 on error */ | |
384 | cupsdEndTLS(cupsd_client_t *con) /* I - Client connection */ | |
385 | { | |
386 | int error; /* Error code */ | |
387 | gnutls_certificate_server_credentials *credentials; | |
388 | /* TLS credentials */ | |
389 | ||
390 | ||
391 | credentials = (gnutls_certificate_server_credentials *) | |
392 | (con->http.tls_credentials); | |
393 | ||
394 | error = gnutls_bye(con->http.tls, GNUTLS_SHUT_WR); | |
395 | switch (error) | |
396 | { | |
397 | case GNUTLS_E_SUCCESS: | |
398 | cupsdLogMessage(CUPSD_LOG_DEBUG, | |
399 | "SSL shutdown successful!"); | |
400 | break; | |
401 | default: | |
402 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
403 | "SSL shutdown failed: %s", gnutls_strerror(error)); | |
404 | break; | |
405 | } | |
406 | ||
407 | gnutls_deinit(con->http.tls); | |
408 | con->http.tls = NULL; | |
409 | ||
410 | gnutls_certificate_free_credentials(*credentials); | |
411 | free(credentials); | |
412 | ||
413 | return (1); | |
414 | } | |
415 | ||
416 | ||
417 | /* | |
418 | * 'cupsdStartTLS()' - Start a secure session with the client. | |
419 | */ | |
420 | ||
421 | int /* O - 1 on success, 0 on error */ | |
422 | cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ | |
423 | { | |
424 | int status; /* Error code */ | |
425 | gnutls_certificate_server_credentials *credentials; | |
426 | /* TLS credentials */ | |
427 | ||
428 | ||
429 | cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.", | |
430 | con->http.fd); | |
431 | ||
432 | /* | |
433 | * Verify that we have a certificate... | |
434 | */ | |
435 | ||
436 | if (access(ServerKey, 0) || access(ServerCertificate, 0)) | |
437 | { | |
438 | /* | |
439 | * Nope, make a self-signed certificate... | |
440 | */ | |
441 | ||
442 | if (!make_certificate(con)) | |
443 | return (0); | |
444 | } | |
445 | ||
446 | /* | |
447 | * Create the SSL object and perform the SSL handshake... | |
448 | */ | |
449 | ||
450 | credentials = (gnutls_certificate_server_credentials *) | |
451 | malloc(sizeof(gnutls_certificate_server_credentials)); | |
452 | if (credentials == NULL) | |
453 | { | |
454 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
455 | "Unable to encrypt connection from %s - %s", | |
456 | con->http.hostname, strerror(errno)); | |
457 | ||
458 | return (0); | |
459 | } | |
460 | ||
461 | gnutls_certificate_allocate_credentials(credentials); | |
462 | gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate, | |
463 | ServerKey, GNUTLS_X509_FMT_PEM); | |
464 | ||
465 | gnutls_init(&con->http.tls, GNUTLS_SERVER); | |
466 | gnutls_set_default_priority(con->http.tls); | |
467 | ||
468 | gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials); | |
dd332638 MS |
469 | gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr_t)HTTP(con)); |
470 | gnutls_transport_set_pull_function(con->http.tls, http_gnutls_read); | |
471 | gnutls_transport_set_push_function(con->http.tls, http_gnutls_write); | |
2c85b752 MS |
472 | |
473 | while ((status = gnutls_handshake(con->http.tls)) != GNUTLS_E_SUCCESS) | |
474 | { | |
475 | if (gnutls_error_is_fatal(status)) | |
476 | { | |
477 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
478 | "Unable to encrypt connection from %s - %s", | |
479 | con->http.hostname, gnutls_strerror(status)); | |
480 | ||
481 | gnutls_deinit(con->http.tls); | |
482 | gnutls_certificate_free_credentials(*credentials); | |
483 | con->http.tls = NULL; | |
484 | free(credentials); | |
485 | return (0); | |
486 | } | |
487 | } | |
488 | ||
489 | cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", | |
490 | con->http.hostname); | |
491 | ||
492 | con->http.tls_credentials = credentials; | |
493 | return (1); | |
494 | } | |
495 | ||
496 | ||
497 | /* | |
498 | * 'make_certificate()' - Make a self-signed SSL/TLS certificate. | |
499 | */ | |
500 | ||
501 | static int /* O - 1 on success, 0 on failure */ | |
502 | make_certificate(cupsd_client_t *con) /* I - Client connection */ | |
503 | { | |
504 | gnutls_x509_crt crt; /* Self-signed certificate */ | |
505 | gnutls_x509_privkey key; /* Encryption key */ | |
506 | cups_lang_t *language; /* Default language info */ | |
507 | cups_file_t *fp; /* Key/cert file */ | |
508 | unsigned char buffer[8192]; /* Buffer for x509 data */ | |
509 | size_t bytes; /* Number of bytes of data */ | |
510 | unsigned char serial[4]; /* Serial number buffer */ | |
511 | time_t curtime; /* Current time */ | |
512 | int result; /* Result of GNU TLS calls */ | |
513 | ||
514 | ||
515 | /* | |
516 | * Create the encryption key... | |
517 | */ | |
518 | ||
519 | cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key..."); | |
520 | ||
521 | gnutls_x509_privkey_init(&key); | |
522 | gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); | |
523 | ||
524 | /* | |
525 | * Save it... | |
526 | */ | |
527 | ||
528 | bytes = sizeof(buffer); | |
529 | ||
530 | if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, | |
531 | buffer, &bytes)) < 0) | |
532 | { | |
533 | cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s", | |
534 | gnutls_strerror(result)); | |
535 | gnutls_x509_privkey_deinit(key); | |
536 | return (0); | |
537 | } | |
538 | else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL) | |
539 | { | |
540 | cupsFileWrite(fp, (char *)buffer, bytes); | |
541 | cupsFileClose(fp); | |
542 | ||
543 | cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...", | |
544 | ServerKey); | |
545 | } | |
546 | else | |
547 | { | |
548 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
549 | "Unable to create SSL server key file \"%s\" - %s", | |
550 | ServerKey, strerror(errno)); | |
551 | gnutls_x509_privkey_deinit(key); | |
552 | return (0); | |
553 | } | |
554 | ||
555 | /* | |
556 | * Create the self-signed certificate... | |
557 | */ | |
558 | ||
559 | cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate..."); | |
560 | ||
561 | language = cupsLangDefault(); | |
562 | curtime = time(NULL); | |
563 | serial[0] = curtime >> 24; | |
564 | serial[1] = curtime >> 16; | |
565 | serial[2] = curtime >> 8; | |
566 | serial[3] = curtime; | |
567 | ||
568 | gnutls_x509_crt_init(&crt); | |
569 | if (strlen(language->language) == 5) | |
570 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, | |
571 | language->language + 3, 2); | |
572 | else | |
573 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, | |
574 | "US", 2); | |
575 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, | |
576 | ServerName, strlen(ServerName)); | |
577 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, | |
578 | ServerName, strlen(ServerName)); | |
579 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, | |
580 | 0, "Unknown", 7); | |
581 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, | |
582 | "Unknown", 7); | |
583 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, | |
584 | "Unknown", 7); | |
585 | gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, | |
586 | ServerAdmin, strlen(ServerAdmin)); | |
587 | gnutls_x509_crt_set_key(crt, key); | |
588 | gnutls_x509_crt_set_serial(crt, serial, sizeof(serial)); | |
589 | gnutls_x509_crt_set_activation_time(crt, curtime); | |
590 | gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400); | |
591 | gnutls_x509_crt_set_ca_status(crt, 0); | |
592 | gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME, | |
593 | ServerName); | |
594 | gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); | |
595 | gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT); | |
596 | gnutls_x509_crt_set_version(crt, 3); | |
597 | ||
598 | bytes = sizeof(buffer); | |
599 | if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) | |
600 | gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes); | |
601 | ||
602 | gnutls_x509_crt_sign(crt, crt, key); | |
603 | ||
604 | /* | |
605 | * Save it... | |
606 | */ | |
607 | ||
608 | bytes = sizeof(buffer); | |
609 | if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, | |
610 | buffer, &bytes)) < 0) | |
611 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
612 | "Unable to export SSL server certificate - %s", | |
613 | gnutls_strerror(result)); | |
614 | else if ((fp = cupsFileOpen(ServerCertificate, "w")) != NULL) | |
615 | { | |
616 | cupsFileWrite(fp, (char *)buffer, bytes); | |
617 | cupsFileClose(fp); | |
618 | ||
619 | cupsdLogMessage(CUPSD_LOG_INFO, | |
620 | "Created SSL server certificate file \"%s\"...", | |
621 | ServerCertificate); | |
622 | } | |
623 | else | |
624 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
625 | "Unable to create SSL server certificate file \"%s\" - %s", | |
626 | ServerCertificate, strerror(errno)); | |
627 | ||
628 | /* | |
629 | * Cleanup... | |
630 | */ | |
631 | ||
632 | gnutls_x509_crt_deinit(crt); | |
633 | gnutls_x509_privkey_deinit(key); | |
634 | ||
635 | return (1); | |
636 | } | |
dd332638 | 637 | #endif /* 0 */ |
2c85b752 MS |
638 | |
639 | ||
640 | /* | |
641 | * End of "$Id$". | |
642 | */ |