]>
Commit | Line | Data |
---|---|---|
82cc1f9a MS |
1 | /* |
2 | * "$Id$" | |
3 | * | |
4 | * TLS support code for the CUPS scheduler on OS X. | |
5 | * | |
e1578ed9 | 6 | * Copyright 2007-2013 by Apple Inc. |
82cc1f9a MS |
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 | * Contents: | |
16 | * | |
17 | * cupsdEndTLS() - Shutdown a secure session with the client. | |
18 | * cupsdStartTLS() - Start a secure session with the client. | |
19 | * copy_cdsa_certificate() - Copy a SSL/TLS certificate from the System | |
20 | * keychain. | |
21 | * make_certificate() - Make a self-signed SSL/TLS certificate. | |
22 | */ | |
23 | ||
24 | ||
25 | /* | |
26 | * Local functions... | |
27 | */ | |
28 | ||
29 | static CFArrayRef copy_cdsa_certificate(cupsd_client_t *con); | |
30 | static int make_certificate(cupsd_client_t *con); | |
31 | ||
32 | ||
33 | /* | |
34 | * 'cupsdEndTLS()' - Shutdown a secure session with the client. | |
35 | */ | |
36 | ||
37 | int /* O - 1 on success, 0 on error */ | |
38 | cupsdEndTLS(cupsd_client_t *con) /* I - Client connection */ | |
39 | { | |
996acce8 | 40 | while (SSLClose(con->http->tls) == errSSLWouldBlock) |
82cc1f9a MS |
41 | usleep(1000); |
42 | ||
996acce8 MS |
43 | CFRelease(con->http->tls); |
44 | con->http->tls = NULL; | |
82cc1f9a | 45 | |
996acce8 MS |
46 | if (con->http->tls_credentials) |
47 | CFRelease(con->http->tls_credentials); | |
82cc1f9a MS |
48 | |
49 | return (1); | |
50 | } | |
51 | ||
52 | ||
53 | /* | |
54 | * 'cupsdStartTLS()' - Start a secure session with the client. | |
55 | */ | |
56 | ||
57 | int /* O - 1 on success, 0 on error */ | |
58 | cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ | |
59 | { | |
60 | OSStatus error = 0; /* Error code */ | |
cb7f98ee | 61 | SecTrustRef peerTrust; /* Peer certificates */ |
82cc1f9a MS |
62 | |
63 | ||
64 | cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.", | |
996acce8 | 65 | con->number); |
82cc1f9a | 66 | |
5ec1fd3d MS |
67 | con->http->encryption = HTTP_ENCRYPTION_ALWAYS; |
68 | ||
996acce8 | 69 | con->http->tls_credentials = copy_cdsa_certificate(con); |
82cc1f9a | 70 | |
996acce8 | 71 | if (!con->http->tls_credentials) |
82cc1f9a MS |
72 | { |
73 | /* | |
74 | * No keychain (yet), make a self-signed certificate... | |
75 | */ | |
76 | ||
77 | if (make_certificate(con)) | |
996acce8 | 78 | con->http->tls_credentials = copy_cdsa_certificate(con); |
82cc1f9a MS |
79 | } |
80 | ||
996acce8 | 81 | if (!con->http->tls_credentials) |
82cc1f9a MS |
82 | { |
83 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
84 | "Could not find signing key in keychain \"%s\"", | |
85 | ServerCertificate); | |
86 | error = errSSLBadConfiguration; | |
87 | } | |
88 | ||
89 | if (!error) | |
996acce8 | 90 | con->http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, |
cb7f98ee | 91 | kSSLStreamType); |
82cc1f9a MS |
92 | |
93 | if (!error) | |
996acce8 | 94 | error = SSLSetIOFuncs(con->http->tls, _httpReadCDSA, _httpWriteCDSA); |
82cc1f9a MS |
95 | |
96 | if (!error) | |
996acce8 | 97 | error = SSLSetConnection(con->http->tls, HTTP(con)); |
82cc1f9a | 98 | |
82cc1f9a | 99 | if (!error) |
996acce8 | 100 | error = SSLSetCertificate(con->http->tls, con->http->tls_credentials); |
82cc1f9a MS |
101 | |
102 | if (!error) | |
103 | { | |
104 | /* | |
105 | * Perform SSL/TLS handshake | |
106 | */ | |
107 | ||
996acce8 | 108 | while ((error = SSLHandshake(con->http->tls)) == errSSLWouldBlock) |
82cc1f9a MS |
109 | usleep(1000); |
110 | } | |
111 | ||
112 | if (error) | |
113 | { | |
114 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
115 | "Unable to encrypt connection from %s - %s (%d)", | |
996acce8 | 116 | con->http->hostname, cssmErrorString(error), (int)error); |
82cc1f9a | 117 | |
996acce8 MS |
118 | con->http->error = error; |
119 | con->http->status = HTTP_ERROR; | |
82cc1f9a | 120 | |
996acce8 | 121 | if (con->http->tls) |
82cc1f9a | 122 | { |
996acce8 MS |
123 | CFRelease(con->http->tls); |
124 | con->http->tls = NULL; | |
82cc1f9a MS |
125 | } |
126 | ||
996acce8 | 127 | if (con->http->tls_credentials) |
82cc1f9a | 128 | { |
996acce8 MS |
129 | CFRelease(con->http->tls_credentials); |
130 | con->http->tls_credentials = NULL; | |
82cc1f9a MS |
131 | } |
132 | ||
133 | return (0); | |
134 | } | |
135 | ||
136 | cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", | |
996acce8 | 137 | con->http->hostname); |
82cc1f9a | 138 | |
996acce8 | 139 | if (!SSLCopyPeerTrust(con->http->tls, &peerTrust) && peerTrust) |
82cc1f9a | 140 | { |
e1578ed9 | 141 | cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates.", |
cb7f98ee MS |
142 | (int)SecTrustGetCertificateCount(peerTrust)); |
143 | CFRelease(peerTrust); | |
82cc1f9a MS |
144 | } |
145 | else | |
e1578ed9 | 146 | cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates."); |
82cc1f9a MS |
147 | |
148 | return (1); | |
149 | } | |
150 | ||
151 | ||
152 | /* | |
153 | * 'copy_cdsa_certificate()' - Copy a SSL/TLS certificate from the System | |
154 | * keychain. | |
155 | */ | |
156 | ||
157 | static CFArrayRef /* O - Array of certificates */ | |
158 | copy_cdsa_certificate( | |
159 | cupsd_client_t *con) /* I - Client connection */ | |
160 | { | |
161 | OSStatus err; /* Error info */ | |
162 | SecKeychainRef keychain = NULL;/* Keychain reference */ | |
163 | SecIdentitySearchRef search = NULL; /* Search reference */ | |
164 | SecIdentityRef identity = NULL;/* Identity */ | |
165 | CFArrayRef certificates = NULL; | |
166 | /* Certificate array */ | |
82cc1f9a MS |
167 | SecPolicyRef policy = NULL; /* Policy ref */ |
168 | CFStringRef servername = NULL; | |
169 | /* Server name */ | |
170 | CFMutableDictionaryRef query = NULL; /* Query qualifiers */ | |
171 | CFArrayRef list = NULL; /* Keychain list */ | |
a29fd7dd | 172 | # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) |
82cc1f9a | 173 | char localname[1024];/* Local hostname */ |
a29fd7dd | 174 | # endif /* HAVE_DNSSD || HAVE_AVAHI */ |
82cc1f9a MS |
175 | |
176 | ||
177 | cupsdLogMessage(CUPSD_LOG_DEBUG, | |
e1578ed9 | 178 | "copy_cdsa_certificate: Looking for certs for \"%s\".", |
82cc1f9a MS |
179 | con->servername); |
180 | ||
181 | if ((err = SecKeychainOpen(ServerCertificate, &keychain))) | |
182 | { | |
183 | cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)", | |
184 | ServerCertificate, cssmErrorString(err), (int)err); | |
185 | goto cleanup; | |
186 | } | |
187 | ||
82cc1f9a MS |
188 | servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername, |
189 | kCFStringEncodingUTF8); | |
190 | ||
191 | policy = SecPolicyCreateSSL(1, servername); | |
192 | ||
193 | if (servername) | |
194 | CFRelease(servername); | |
195 | ||
196 | if (!policy) | |
197 | { | |
198 | cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); | |
199 | goto cleanup; | |
200 | } | |
201 | ||
202 | if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | |
203 | &kCFTypeDictionaryKeyCallBacks, | |
204 | &kCFTypeDictionaryValueCallBacks))) | |
205 | { | |
206 | cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary"); | |
207 | goto cleanup; | |
208 | } | |
209 | ||
210 | list = CFArrayCreate(kCFAllocatorDefault, (const void **)&keychain, 1, | |
211 | &kCFTypeArrayCallBacks); | |
212 | ||
213 | CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); | |
214 | CFDictionaryAddValue(query, kSecMatchPolicy, policy); | |
215 | CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); | |
216 | CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne); | |
217 | CFDictionaryAddValue(query, kSecMatchSearchList, list); | |
218 | ||
219 | CFRelease(list); | |
220 | ||
221 | err = SecItemCopyMatching(query, (CFTypeRef *)&identity); | |
222 | ||
a29fd7dd | 223 | # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) |
82cc1f9a MS |
224 | if (err && DNSSDHostName) |
225 | { | |
226 | /* | |
227 | * Search for the connection server name failed; try the DNS-SD .local | |
228 | * hostname instead... | |
229 | */ | |
230 | ||
231 | snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); | |
232 | ||
233 | cupsdLogMessage(CUPSD_LOG_DEBUG, | |
e1578ed9 | 234 | "copy_cdsa_certificate: Looking for certs for \"%s\".", |
82cc1f9a MS |
235 | localname); |
236 | ||
237 | servername = CFStringCreateWithCString(kCFAllocatorDefault, localname, | |
238 | kCFStringEncodingUTF8); | |
239 | ||
240 | CFRelease(policy); | |
241 | ||
242 | policy = SecPolicyCreateSSL(1, servername); | |
243 | ||
244 | if (servername) | |
245 | CFRelease(servername); | |
246 | ||
247 | if (!policy) | |
248 | { | |
249 | cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); | |
250 | goto cleanup; | |
251 | } | |
252 | ||
253 | CFDictionarySetValue(query, kSecMatchPolicy, policy); | |
254 | ||
255 | err = SecItemCopyMatching(query, (CFTypeRef *)&identity); | |
256 | } | |
a29fd7dd | 257 | # endif /* HAVE_DNSSD || HAVE_AVAHI */ |
82cc1f9a MS |
258 | |
259 | if (err) | |
260 | { | |
261 | cupsdLogMessage(CUPSD_LOG_DEBUG, | |
262 | "Cannot find signing key in keychain \"%s\": %s (%d)", | |
263 | ServerCertificate, cssmErrorString(err), (int)err); | |
264 | goto cleanup; | |
265 | } | |
266 | ||
82cc1f9a MS |
267 | if (CFGetTypeID(identity) != SecIdentityGetTypeID()) |
268 | { | |
e1578ed9 | 269 | cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure."); |
82cc1f9a MS |
270 | goto cleanup; |
271 | } | |
272 | ||
273 | if ((certificates = CFArrayCreate(NULL, (const void **)&identity, | |
274 | 1, &kCFTypeArrayCallBacks)) == NULL) | |
275 | { | |
276 | cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array"); | |
277 | goto cleanup; | |
278 | } | |
279 | ||
280 | cleanup : | |
281 | ||
282 | if (keychain) | |
283 | CFRelease(keychain); | |
284 | if (search) | |
285 | CFRelease(search); | |
286 | if (identity) | |
287 | CFRelease(identity); | |
288 | ||
82cc1f9a MS |
289 | if (policy) |
290 | CFRelease(policy); | |
291 | if (query) | |
292 | CFRelease(query); | |
82cc1f9a MS |
293 | |
294 | return (certificates); | |
295 | } | |
296 | ||
297 | ||
298 | /* | |
299 | * 'make_certificate()' - Make a self-signed SSL/TLS certificate. | |
300 | */ | |
301 | ||
302 | static int /* O - 1 on success, 0 on failure */ | |
303 | make_certificate(cupsd_client_t *con) /* I - Client connection */ | |
304 | { | |
e1578ed9 MS |
305 | # ifdef HAVE_SECGENERATESELFSIGNEDCERTIFICATE |
306 | int status = 0; /* Return status */ | |
307 | OSStatus err; /* Error code (if any) */ | |
308 | # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) | |
309 | char localname[1024];/* Local hostname */ | |
310 | # endif /* HAVE_DNSSD || HAVE_AVAHI */ | |
311 | const char *servername; /* Name of server in cert */ | |
312 | CFStringRef cfservername = NULL; | |
313 | /* CF string for server name */ | |
314 | SecIdentityRef ident = NULL; /* Identity */ | |
315 | SecKeyRef publicKey = NULL, | |
316 | /* Public key */ | |
317 | privateKey = NULL; | |
318 | /* Private key */ | |
319 | CFMutableDictionaryRef keyParams = NULL; | |
320 | /* Key generation parameters */ | |
321 | ||
322 | ||
323 | cupsdLogMessage(CUPSD_LOG_INFO, | |
324 | "Generating SSL server key and certificate."); | |
325 | ||
326 | # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) | |
327 | if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) | |
328 | { | |
329 | snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); | |
330 | servername = localname; | |
331 | } | |
332 | else | |
333 | # endif /* HAVE_DNSSD || HAVE_AVAHI */ | |
334 | servername = con->servername; | |
335 | ||
336 | cfservername = CFStringCreateWithCString(kCFAllocatorDefault, servername, | |
337 | kCFStringEncodingUTF8); | |
338 | if (!cfservername) | |
339 | goto cleanup; | |
340 | ||
341 | /* | |
342 | * Create a public/private key pair... | |
343 | */ | |
344 | ||
345 | keyParams = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | |
346 | &kCFTypeDictionaryKeyCallBacks, | |
347 | &kCFTypeDictionaryValueCallBacks); | |
348 | if (!keyParams) | |
349 | goto cleanup; | |
350 | ||
351 | CFDictionaryAddValue(keyParams, kSecAttrKeyType, kSecAttrKeyTypeRSA); | |
352 | CFDictionaryAddValue(keyParams, kSecAttrKeySizeInBits, CFSTR("2048")); | |
353 | CFDictionaryAddValue(keyParams, kSecAttrLabel, | |
354 | CFSTR("CUPS Self-Signed Certificate")); | |
355 | ||
356 | err = SecKeyGeneratePair(keyParams, &publicKey, &privateKey); | |
357 | if (err != noErr) | |
358 | { | |
359 | cupsdLogMessage(CUPSD_LOG_DEBUG, "SecKeyGeneratePair returned %ld.", | |
360 | (long)err); | |
361 | goto cleanup; | |
362 | } | |
363 | ||
364 | /* | |
365 | * Create a self-signed certificate using the public/private key pair... | |
366 | */ | |
367 | ||
368 | CFIndex usageInt = kSecKeyUsageAll; | |
369 | CFNumberRef usage = CFNumberCreate(alloc, kCFNumberCFIndexType, &usageInt); | |
370 | CFDictionaryRef certParams = CFDictionaryCreateMutable(kCFAllocatorDefault, | |
371 | kSecCSRBasicContraintsPathLen, CFINT(0), | |
372 | kSecSubjectAltName, cfservername, | |
373 | kSecCertificateKeyUsage, usage, | |
374 | NULL, NULL); | |
375 | CFRelease(usage); | |
376 | ||
377 | const void *ca_o[] = { kSecOidOrganization, CFSTR("") }; | |
378 | const void *ca_cn[] = { kSecOidCommonName, cfservername }; | |
379 | CFArrayRef ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL); | |
380 | CFArrayRef ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL); | |
381 | const void *ca_dn_array[2]; | |
382 | ||
383 | ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn, | |
384 | 1, NULL); | |
385 | ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn, | |
386 | 1, NULL); | |
387 | ||
388 | CFArrayRef subject = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2, | |
389 | NULL); | |
390 | SecCertificateRef cert = SecGenerateSelfSignedCertificate(subject, certParams, | |
391 | publicKey, | |
392 | privateKey); | |
393 | CFRelease(subject); | |
394 | CFRelease(certParams); | |
395 | ||
396 | if (!cert) | |
397 | { | |
398 | cupsdLogMessage(CUPSD_LOG_DEBUG, "SecGenerateSelfSignedCertificate failed."); | |
399 | goto cleanup; | |
400 | } | |
401 | ||
402 | ident = SecIdentityCreate(kCFAllocatorDefault, cert, privateKey); | |
403 | ||
404 | if (ident) | |
405 | cupsdLogMessage(CUPSD_LOG_INFO, | |
406 | "Created SSL server certificate file \"%s\".", | |
407 | ServerCertificate); | |
408 | ||
409 | /* | |
410 | * Cleanup and return... | |
411 | */ | |
412 | ||
413 | cleanup: | |
414 | ||
415 | if (cfservername) | |
416 | CFRelease(cfservername); | |
417 | ||
418 | if (keyParams) | |
419 | CFRelease(keyParams); | |
420 | ||
421 | if (ident) | |
422 | CFRelease(ident); | |
423 | ||
424 | if (cert) | |
425 | CFRelease(cert); | |
426 | ||
427 | if (publicKey) | |
428 | CFRelease(publicKey); | |
429 | ||
430 | if (privateKey) | |
431 | CFRelease(publicKey); | |
432 | ||
433 | if (!status) | |
434 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
435 | "Unable to create SSL server key and certificate."); | |
436 | ||
437 | return (status); | |
438 | ||
439 | # else /* !HAVE_SECGENERATESELFSIGNEDCERTIFICATE */ | |
82cc1f9a MS |
440 | int pid, /* Process ID of command */ |
441 | status; /* Status of command */ | |
442 | char command[1024], /* Command */ | |
443 | *argv[4], /* Command-line arguments */ | |
444 | *envp[MAX_ENV + 1], /* Environment variables */ | |
445 | keychain[1024], /* Keychain argument */ | |
446 | infofile[1024], /* Type-in information for cert */ | |
e1578ed9 | 447 | # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) |
82cc1f9a | 448 | localname[1024], /* Local hostname */ |
e1578ed9 | 449 | # endif /* HAVE_DNSSD || HAVE_AVAHI */ |
82cc1f9a MS |
450 | *servername; /* Name of server in cert */ |
451 | cups_file_t *fp; /* Seed/info file */ | |
452 | int infofd; /* Info file descriptor */ | |
453 | ||
454 | ||
e1578ed9 | 455 | # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) |
82cc1f9a MS |
456 | if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) |
457 | { | |
458 | snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); | |
459 | servername = localname; | |
460 | } | |
461 | else | |
e1578ed9 | 462 | # endif /* HAVE_DNSSD || HAVE_AVAHI */ |
82cc1f9a MS |
463 | servername = con->servername; |
464 | ||
465 | /* | |
466 | * Run the "certtool" command to generate a self-signed certificate... | |
467 | */ | |
468 | ||
469 | if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command))) | |
470 | { | |
471 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
e1578ed9 | 472 | "No SSL certificate and certtool command not found."); |
82cc1f9a MS |
473 | return (0); |
474 | } | |
475 | ||
476 | /* | |
477 | * Create a file with the certificate information fields... | |
478 | * | |
479 | * Note: This assumes that the default questions are asked by the certtool | |
480 | * command... | |
481 | */ | |
482 | ||
483 | if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) | |
484 | { | |
485 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
486 | "Unable to create certificate information file %s - %s", | |
487 | infofile, strerror(errno)); | |
488 | return (0); | |
489 | } | |
490 | ||
491 | cupsFilePrintf(fp, | |
492 | "%s\n" /* Enter key and certificate label */ | |
493 | "r\n" /* Generate RSA key pair */ | |
494 | "2048\n" /* Key size in bits */ | |
495 | "y\n" /* OK (y = yes) */ | |
496 | "b\n" /* Usage (b=signing/encryption) */ | |
497 | "s\n" /* Sign with SHA1 */ | |
498 | "y\n" /* OK (y = yes) */ | |
499 | "%s\n" /* Common name */ | |
500 | "\n" /* Country (default) */ | |
501 | "\n" /* Organization (default) */ | |
502 | "\n" /* Organizational unit (default) */ | |
503 | "\n" /* State/Province (default) */ | |
504 | "%s\n" /* Email address */ | |
505 | "y\n", /* OK (y = yes) */ | |
506 | servername, servername, ServerAdmin); | |
507 | cupsFileClose(fp); | |
508 | ||
509 | cupsdLogMessage(CUPSD_LOG_INFO, | |
e1578ed9 | 510 | "Generating SSL server key and certificate."); |
82cc1f9a MS |
511 | |
512 | snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate); | |
513 | ||
514 | argv[0] = "certtool"; | |
515 | argv[1] = "c"; | |
516 | argv[2] = keychain; | |
517 | argv[3] = NULL; | |
518 | ||
519 | cupsdLoadEnv(envp, MAX_ENV); | |
520 | ||
521 | infofd = open(infofile, O_RDONLY); | |
522 | ||
523 | if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, | |
524 | NULL, &pid)) | |
525 | { | |
526 | close(infofd); | |
527 | unlink(infofile); | |
528 | return (0); | |
529 | } | |
530 | ||
531 | close(infofd); | |
532 | unlink(infofile); | |
533 | ||
534 | while (waitpid(pid, &status, 0) < 0) | |
535 | if (errno != EINTR) | |
536 | { | |
537 | status = 1; | |
538 | break; | |
539 | } | |
540 | ||
541 | cupsdFinishProcess(pid, command, sizeof(command), NULL); | |
542 | ||
543 | if (status) | |
544 | { | |
545 | if (WIFEXITED(status)) | |
546 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
547 | "Unable to create SSL server key and certificate - " | |
e1578ed9 | 548 | "the certtool command stopped with status %d.", |
82cc1f9a MS |
549 | WEXITSTATUS(status)); |
550 | else | |
551 | cupsdLogMessage(CUPSD_LOG_ERROR, | |
552 | "Unable to create SSL server key and certificate - " | |
e1578ed9 | 553 | "the certtool command crashed on signal %d.", |
82cc1f9a MS |
554 | WTERMSIG(status)); |
555 | } | |
556 | else | |
557 | { | |
558 | cupsdLogMessage(CUPSD_LOG_INFO, | |
e1578ed9 | 559 | "Created SSL server certificate file \"%s\".", |
82cc1f9a MS |
560 | ServerCertificate); |
561 | } | |
562 | ||
563 | return (!status); | |
e1578ed9 | 564 | # endif /* HAVE_SECGENERATESELFSIGNEDCERTIFICATE */ |
82cc1f9a MS |
565 | } |
566 | ||
567 | ||
568 | /* | |
569 | * End of "$Id$". | |
570 | */ |