1 /*
2  * TLS check program for CUPS.
3  *
4  * Copyright 2007-2017 by Apple Inc.
5  * Copyright 1997-2006 by Easy Software Products.
6  *
7  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
8  */
9 
10 /*
11  * Include necessary headers...
12  */
13 
14 #include "cups-private.h"
15 
16 
17 #ifndef HAVE_SSL
main(void)18 int main(void) { puts("Sorry, no TLS support compiled in."); return (1); }
19 #else
20 
21 /*
22  * Local functions...
23  */
24 
25 static void	usage(void);
26 
27 
28 /*
29  * 'main()' - Main entry.
30  */
31 
32 int					/* O - Exit status */
main(int argc,char * argv[])33 main(int  argc,				/* I - Number of command-line arguments */
34      char *argv[])			/* I - Command-line arguments */
35 {
36   int		i;			/* Looping var */
37   http_t	*http;			/* HTTP connection */
38   const char	*server = NULL;		/* Hostname from command-line */
39   int		port = 0;		/* Port number */
40   cups_array_t	*creds;			/* Server credentials */
41   char		creds_str[2048];	/* Credentials string */
42   const char	*cipherName = "UNKNOWN";/* Cipher suite name */
43   int		dhBits = 0;		/* Diffie-Hellman bits */
44   int		tlsVersion = 0;		/* TLS version number */
45   char		uri[1024],		/* Printer URI */
46 		scheme[32],		/* URI scheme */
47 		host[256],		/* Hostname */
48 		userpass[256],		/* Username/password */
49 		resource[256];		/* Resource path */
50   int		af = AF_UNSPEC,		/* Address family */
51 		tls_options = _HTTP_TLS_NONE,
52 					/* TLS options */
53 		tls_min_version = _HTTP_TLS_1_0,
54 		tls_max_version = _HTTP_TLS_MAX,
55 		verbose = 0;		/* Verbosity */
56   ipp_t		*request,		/* IPP Get-Printer-Attributes request */
57 		*response;		/* IPP Get-Printer-Attributes response */
58   ipp_attribute_t *attr;		/* Current attribute */
59   const char	*name;			/* Attribute name */
60   char		value[1024];		/* Attribute (string) value */
61   static const char * const pattrs[] =	/* Requested attributes */
62   {
63     "color-supported",
64     "compression-supported",
65     "document-format-supported",
66     "pages-per-minute",
67     "printer-location",
68     "printer-make-and-model",
69     "printer-state",
70     "printer-state-reasons",
71     "sides-supported",
72     "uri-authentication-supported",
73     "uri-security-supported"
74   };
75 
76 
77   for (i = 1; i < argc; i ++)
78   {
79     if (!strcmp(argv[i], "--dh"))
80     {
81       tls_options |= _HTTP_TLS_ALLOW_DH;
82     }
83     else if (!strcmp(argv[i], "--no-cbc"))
84     {
85       tls_options |= _HTTP_TLS_DENY_CBC;
86     }
87     else if (!strcmp(argv[i], "--no-tls10"))
88     {
89       tls_min_version = _HTTP_TLS_1_1;
90     }
91     else if (!strcmp(argv[i], "--tls10"))
92     {
93       tls_min_version = _HTTP_TLS_1_0;
94       tls_max_version = _HTTP_TLS_1_0;
95     }
96     else if (!strcmp(argv[i], "--tls11"))
97     {
98       tls_min_version = _HTTP_TLS_1_1;
99       tls_max_version = _HTTP_TLS_1_1;
100     }
101     else if (!strcmp(argv[i], "--tls12"))
102     {
103       tls_min_version = _HTTP_TLS_1_2;
104       tls_max_version = _HTTP_TLS_1_2;
105     }
106     else if (!strcmp(argv[i], "--tls13"))
107     {
108       tls_min_version = _HTTP_TLS_1_3;
109       tls_max_version = _HTTP_TLS_1_3;
110     }
111     else if (!strcmp(argv[i], "--rc4"))
112     {
113       tls_options |= _HTTP_TLS_ALLOW_RC4;
114     }
115     else if (!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v"))
116     {
117       verbose = 1;
118     }
119     else if (!strcmp(argv[i], "-4"))
120     {
121       af = AF_INET;
122     }
123     else if (!strcmp(argv[i], "-6"))
124     {
125       af = AF_INET6;
126     }
127     else if (argv[i][0] == '-')
128     {
129       printf("tlscheck: Unknown option '%s'.\n", argv[i]);
130       usage();
131     }
132     else if (!server)
133     {
134       if (!strncmp(argv[i], "ipps://", 7))
135       {
136         httpSeparateURI(HTTP_URI_CODING_ALL, argv[i], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource));
137         server = host;
138       }
139       else
140       {
141         server = argv[i];
142         strlcpy(resource, "/ipp/print", sizeof(resource));
143       }
144     }
145     else if (!port && (argv[i][0] == '=' || isdigit(argv[i][0] & 255)))
146     {
147       if (argv[i][0] == '=')
148 	port = atoi(argv[i] + 1);
149       else
150 	port = atoi(argv[i]);
151     }
152     else
153     {
154       printf("tlscheck: Unexpected argument '%s'.\n", argv[i]);
155       usage();
156     }
157   }
158 
159   if (!server)
160     usage();
161 
162   if (!port)
163     port = 631;
164 
165   _httpTLSSetOptions(tls_options, tls_min_version, tls_max_version);
166 
167   http = httpConnect2(server, port, NULL, af, HTTP_ENCRYPTION_ALWAYS, 1, 30000, NULL);
168   if (!http)
169   {
170     printf("%s: ERROR (%s)\n", server, cupsLastErrorString());
171     return (1);
172   }
173 
174   if (httpCopyCredentials(http, &creds))
175   {
176     strlcpy(creds_str, "Unable to get server X.509 credentials.", sizeof(creds_str));
177   }
178   else
179   {
180     httpCredentialsString(creds, creds_str, sizeof(creds_str));
181     httpFreeCredentials(creds);
182   }
183 
184 #ifdef __APPLE__
185   SSLProtocol protocol;
186   SSLCipherSuite cipher;
187   char unknownCipherName[256];
188   int paramsNeeded = 0;
189   const void *params;
190   size_t paramsLen;
191   OSStatus err;
192 
193   if ((err = SSLGetNegotiatedProtocolVersion(http->tls, &protocol)) != noErr)
194   {
195     printf("%s: ERROR (No protocol version - %d)\n", server, (int)err);
196     httpClose(http);
197     return (1);
198   }
199 
200   switch (protocol)
201   {
202     default :
203         tlsVersion = 0;
204         break;
205     case kSSLProtocol3 :
206         tlsVersion = 30;
207         break;
208     case kTLSProtocol1 :
209         tlsVersion = 10;
210         break;
211     case kTLSProtocol11 :
212         tlsVersion = 11;
213         break;
214     case kTLSProtocol12 :
215         tlsVersion = 12;
216         break;
217   }
218 
219   if ((err = SSLGetNegotiatedCipher(http->tls, &cipher)) != noErr)
220   {
221     printf("%s: ERROR (No cipher suite - %d)\n", server, (int)err);
222     httpClose(http);
223     return (1);
224   }
225 
226   switch (cipher)
227   {
228     case TLS_NULL_WITH_NULL_NULL:
229 	cipherName = "TLS_NULL_WITH_NULL_NULL";
230 	break;
231     case TLS_RSA_WITH_NULL_MD5:
232 	cipherName = "TLS_RSA_WITH_NULL_MD5";
233 	break;
234     case TLS_RSA_WITH_NULL_SHA:
235 	cipherName = "TLS_RSA_WITH_NULL_SHA";
236 	break;
237     case TLS_RSA_WITH_RC4_128_MD5:
238 	cipherName = "TLS_RSA_WITH_RC4_128_MD5";
239 	break;
240     case TLS_RSA_WITH_RC4_128_SHA:
241 	cipherName = "TLS_RSA_WITH_RC4_128_SHA";
242 	break;
243     case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
244 	cipherName = "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
245 	break;
246     case TLS_RSA_WITH_NULL_SHA256:
247 	cipherName = "TLS_RSA_WITH_NULL_SHA256";
248 	break;
249     case TLS_RSA_WITH_AES_128_CBC_SHA256:
250 	cipherName = "TLS_RSA_WITH_AES_128_CBC_SHA256";
251 	break;
252     case TLS_RSA_WITH_AES_256_CBC_SHA256:
253 	cipherName = "TLS_RSA_WITH_AES_256_CBC_SHA256";
254 	break;
255     case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
256 	cipherName = "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
257 	paramsNeeded = 1;
258 	break;
259     case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
260 	cipherName = "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
261 	paramsNeeded = 1;
262 	break;
263     case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
264 	cipherName = "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
265 	paramsNeeded = 1;
266 	break;
267     case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
268 	cipherName = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
269 	paramsNeeded = 1;
270 	break;
271     case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
272 	cipherName = "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
273 	paramsNeeded = 1;
274 	break;
275     case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
276 	cipherName = "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
277 	paramsNeeded = 1;
278 	break;
279     case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
280 	cipherName = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
281 	paramsNeeded = 1;
282 	break;
283     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
284 	cipherName = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
285 	paramsNeeded = 1;
286 	break;
287     case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
288 	cipherName = "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
289 	paramsNeeded = 1;
290 	break;
291     case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
292 	cipherName = "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
293 	paramsNeeded = 1;
294 	break;
295     case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
296 	cipherName = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
297 	paramsNeeded = 1;
298 	break;
299     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
300 	cipherName = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
301 	paramsNeeded = 1;
302 	break;
303     case TLS_DH_anon_WITH_RC4_128_MD5:
304 	cipherName = "TLS_DH_anon_WITH_RC4_128_MD5";
305 	paramsNeeded = 1;
306 	break;
307     case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
308 	cipherName = "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
309 	paramsNeeded = 1;
310 	break;
311     case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
312 	cipherName = "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
313 	paramsNeeded = 1;
314 	break;
315     case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
316 	cipherName = "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
317 	paramsNeeded = 1;
318 	break;
319     case TLS_PSK_WITH_RC4_128_SHA:
320 	cipherName = "TLS_PSK_WITH_RC4_128_SHA";
321 	break;
322     case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
323 	cipherName = "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
324 	break;
325     case TLS_PSK_WITH_AES_128_CBC_SHA:
326 	cipherName = "TLS_PSK_WITH_AES_128_CBC_SHA";
327 	break;
328     case TLS_PSK_WITH_AES_256_CBC_SHA:
329 	cipherName = "TLS_PSK_WITH_AES_256_CBC_SHA";
330 	break;
331     case TLS_DHE_PSK_WITH_RC4_128_SHA:
332 	cipherName = "TLS_DHE_PSK_WITH_RC4_128_SHA";
333 	paramsNeeded = 1;
334 	break;
335     case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
336 	cipherName = "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
337 	paramsNeeded = 1;
338 	break;
339     case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
340 	cipherName = "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
341 	paramsNeeded = 1;
342 	break;
343     case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
344 	cipherName = "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
345 	paramsNeeded = 1;
346 	break;
347     case TLS_RSA_PSK_WITH_RC4_128_SHA:
348 	cipherName = "TLS_RSA_PSK_WITH_RC4_128_SHA";
349 	break;
350     case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
351 	cipherName = "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
352 	break;
353     case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
354 	cipherName = "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
355 	break;
356     case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
357 	cipherName = "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
358 	break;
359     case TLS_PSK_WITH_NULL_SHA:
360 	cipherName = "TLS_PSK_WITH_NULL_SHA";
361 	break;
362     case TLS_DHE_PSK_WITH_NULL_SHA:
363 	cipherName = "TLS_DHE_PSK_WITH_NULL_SHA";
364 	paramsNeeded = 1;
365 	break;
366     case TLS_RSA_PSK_WITH_NULL_SHA:
367 	cipherName = "TLS_RSA_PSK_WITH_NULL_SHA";
368 	break;
369     case TLS_RSA_WITH_AES_128_GCM_SHA256:
370 	cipherName = "TLS_RSA_WITH_AES_128_GCM_SHA256";
371 	break;
372     case TLS_RSA_WITH_AES_256_GCM_SHA384:
373 	cipherName = "TLS_RSA_WITH_AES_256_GCM_SHA384";
374 	break;
375     case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
376 	cipherName = "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
377 	paramsNeeded = 1;
378 	break;
379     case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
380 	cipherName = "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
381 	paramsNeeded = 1;
382 	break;
383     case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
384 	cipherName = "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
385 	paramsNeeded = 1;
386 	break;
387     case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
388 	cipherName = "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
389 	paramsNeeded = 1;
390 	break;
391     case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
392 	cipherName = "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
393 	paramsNeeded = 1;
394 	break;
395     case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
396 	cipherName = "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
397 	paramsNeeded = 1;
398 	break;
399     case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
400 	cipherName = "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
401 	paramsNeeded = 1;
402 	break;
403     case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
404 	cipherName = "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
405 	paramsNeeded = 1;
406 	break;
407     case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
408 	cipherName = "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
409 	paramsNeeded = 1;
410 	break;
411     case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
412 	cipherName = "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
413 	paramsNeeded = 1;
414 	break;
415     case TLS_PSK_WITH_AES_128_GCM_SHA256:
416 	cipherName = "TLS_PSK_WITH_AES_128_GCM_SHA256";
417 	break;
418     case TLS_PSK_WITH_AES_256_GCM_SHA384:
419 	cipherName = "TLS_PSK_WITH_AES_256_GCM_SHA384";
420 	break;
421     case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
422 	cipherName = "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
423 	paramsNeeded = 1;
424 	break;
425     case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
426 	cipherName = "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
427 	paramsNeeded = 1;
428 	break;
429     case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
430 	cipherName = "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
431 	break;
432     case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
433 	cipherName = "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384";
434 	break;
435     case TLS_PSK_WITH_AES_128_CBC_SHA256:
436 	cipherName = "TLS_PSK_WITH_AES_128_CBC_SHA256";
437 	break;
438     case TLS_PSK_WITH_AES_256_CBC_SHA384:
439 	cipherName = "TLS_PSK_WITH_AES_256_CBC_SHA384";
440 	break;
441     case TLS_PSK_WITH_NULL_SHA256:
442 	cipherName = "TLS_PSK_WITH_NULL_SHA256";
443 	break;
444     case TLS_PSK_WITH_NULL_SHA384:
445 	cipherName = "TLS_PSK_WITH_NULL_SHA384";
446 	break;
447     case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
448 	cipherName = "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
449 	paramsNeeded = 1;
450 	break;
451     case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
452 	cipherName = "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
453 	paramsNeeded = 1;
454 	break;
455     case TLS_DHE_PSK_WITH_NULL_SHA256:
456 	cipherName = "TLS_DHE_PSK_WITH_NULL_SHA256";
457 	paramsNeeded = 1;
458 	break;
459     case TLS_DHE_PSK_WITH_NULL_SHA384:
460 	cipherName = "TLS_DHE_PSK_WITH_NULL_SHA384";
461 	paramsNeeded = 1;
462 	break;
463     case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
464 	cipherName = "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
465 	break;
466     case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
467 	cipherName = "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
468 	break;
469     case TLS_RSA_PSK_WITH_NULL_SHA256:
470 	cipherName = "TLS_RSA_PSK_WITH_NULL_SHA256";
471 	break;
472     case TLS_RSA_PSK_WITH_NULL_SHA384:
473 	cipherName = "TLS_RSA_PSK_WITH_NULL_SHA384";
474 	break;
475     case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
476 	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
477 	paramsNeeded = 1;
478 	break;
479     case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
480 	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
481 	paramsNeeded = 1;
482 	break;
483     case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
484 	cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
485 	paramsNeeded = 1;
486 	break;
487     case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
488 	cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
489 	paramsNeeded = 1;
490 	break;
491     case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
492 	cipherName = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
493 	paramsNeeded = 1;
494 	break;
495     case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
496 	cipherName = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
497 	paramsNeeded = 1;
498 	break;
499     case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
500 	cipherName = "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
501 	paramsNeeded = 1;
502 	break;
503     case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
504 	cipherName = "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
505 	paramsNeeded = 1;
506 	break;
507     case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
508 	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
509 	paramsNeeded = 1;
510 	break;
511     case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
512 	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
513 	paramsNeeded = 1;
514 	break;
515     case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
516 	cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
517 	paramsNeeded = 1;
518 	break;
519     case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
520 	cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
521 	paramsNeeded = 1;
522 	break;
523     case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
524 	cipherName = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
525 	paramsNeeded = 1;
526 	break;
527     case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
528 	cipherName = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
529 	paramsNeeded = 1;
530 	break;
531     case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
532 	cipherName = "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
533 	paramsNeeded = 1;
534 	break;
535     case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
536 	cipherName = "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
537 	paramsNeeded = 1;
538 	break;
539     case TLS_RSA_WITH_AES_128_CBC_SHA:
540 	cipherName = "TLS_RSA_WITH_AES_128_CBC_SHA";
541 	break;
542     case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
543 	cipherName = "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
544 	paramsNeeded = 1;
545 	break;
546     case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
547 	cipherName = "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
548 	paramsNeeded = 1;
549 	break;
550     case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
551 	cipherName = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
552 	paramsNeeded = 1;
553 	break;
554     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
555 	cipherName = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
556 	paramsNeeded = 1;
557 	break;
558     case TLS_DH_anon_WITH_AES_128_CBC_SHA:
559 	cipherName = "TLS_DH_anon_WITH_AES_128_CBC_SHA";
560 	paramsNeeded = 1;
561 	break;
562     case TLS_RSA_WITH_AES_256_CBC_SHA:
563 	cipherName = "TLS_RSA_WITH_AES_256_CBC_SHA";
564 	break;
565     case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
566 	cipherName = "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
567 	paramsNeeded = 1;
568 	break;
569     case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
570 	cipherName = "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
571 	paramsNeeded = 1;
572 	break;
573     case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
574 	cipherName = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
575 	paramsNeeded = 1;
576 	break;
577     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
578 	cipherName = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
579 	paramsNeeded = 1;
580 	break;
581     case TLS_DH_anon_WITH_AES_256_CBC_SHA:
582 	cipherName = "TLS_DH_anon_WITH_AES_256_CBC_SHA";
583 	paramsNeeded = 1;
584 	break;
585     case TLS_ECDH_ECDSA_WITH_NULL_SHA:
586 	cipherName = "TLS_ECDH_ECDSA_WITH_NULL_SHA";
587 	paramsNeeded = 1;
588 	break;
589     case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
590 	cipherName = "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
591 	paramsNeeded = 1;
592 	break;
593     case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
594 	cipherName = "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
595 	paramsNeeded = 1;
596 	break;
597     case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
598 	cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
599 	paramsNeeded = 1;
600 	break;
601     case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
602 	cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
603 	paramsNeeded = 1;
604 	break;
605     case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
606 	cipherName = "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
607 	paramsNeeded = 1;
608 	break;
609     case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
610 	cipherName = "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
611 	paramsNeeded = 1;
612 	break;
613     case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
614 	cipherName = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
615 	paramsNeeded = 1;
616 	break;
617     case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
618 	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
619 	paramsNeeded = 1;
620 	break;
621     case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
622 	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
623 	paramsNeeded = 1;
624 	break;
625     case TLS_ECDH_RSA_WITH_NULL_SHA:
626 	cipherName = "TLS_ECDH_RSA_WITH_NULL_SHA";
627 	paramsNeeded = 1;
628 	break;
629     case TLS_ECDH_RSA_WITH_RC4_128_SHA:
630 	cipherName = "TLS_ECDH_RSA_WITH_RC4_128_SHA";
631 	paramsNeeded = 1;
632 	break;
633     case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
634 	cipherName = "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
635 	paramsNeeded = 1;
636 	break;
637     case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
638 	cipherName = "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
639 	paramsNeeded = 1;
640 	break;
641     case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
642 	cipherName = "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
643 	paramsNeeded = 1;
644 	break;
645     case TLS_ECDHE_RSA_WITH_NULL_SHA:
646 	cipherName = "TLS_ECDHE_RSA_WITH_NULL_SHA";
647 	paramsNeeded = 1;
648 	break;
649     case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
650 	cipherName = "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
651 	paramsNeeded = 1;
652 	break;
653     case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
654 	cipherName = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
655 	paramsNeeded = 1;
656 	break;
657     case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
658 	cipherName = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
659 	paramsNeeded = 1;
660 	break;
661     case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
662 	cipherName = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
663 	paramsNeeded = 1;
664 	break;
665     case TLS_ECDH_anon_WITH_NULL_SHA:
666 	cipherName = "TLS_ECDH_anon_WITH_NULL_SHA";
667 	paramsNeeded = 1;
668 	break;
669     case TLS_ECDH_anon_WITH_RC4_128_SHA:
670 	cipherName = "TLS_ECDH_anon_WITH_RC4_128_SHA";
671 	paramsNeeded = 1;
672 	break;
673     case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
674 	cipherName = "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
675 	paramsNeeded = 1;
676 	break;
677     case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
678 	cipherName = "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
679 	paramsNeeded = 1;
680 	break;
681     case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
682 	cipherName = "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
683 	paramsNeeded = 1;
684 	break;
685     default :
686         snprintf(unknownCipherName, sizeof(unknownCipherName), "UNKNOWN_%04X", cipher);
687         cipherName = unknownCipherName;
688         break;
689   }
690 
691   if (cipher == TLS_RSA_WITH_RC4_128_MD5 ||
692       cipher == TLS_RSA_WITH_RC4_128_SHA)
693   {
694     printf("%s: ERROR (Printers MUST NOT negotiate RC4 cipher suites.)\n", server);
695     httpClose(http);
696     return (1);
697   }
698 
699   if ((err = SSLGetDiffieHellmanParams(http->tls, &params, &paramsLen)) != noErr && paramsNeeded)
700   {
701     printf("%s: ERROR (Unable to get Diffie-Hellman parameters - %d)\n", server, (int)err);
702     httpClose(http);
703     return (1);
704   }
705 
706   if (paramsLen < 128 && paramsLen != 0)
707   {
708     printf("%s: ERROR (Diffie-Hellman parameters MUST be at least 2048 bits, but Printer uses only %d bits/%d bytes)\n", server, (int)paramsLen * 8, (int)paramsLen);
709     httpClose(http);
710     return (1);
711   }
712 
713   dhBits = (int)paramsLen * 8;
714 #endif /* __APPLE__ */
715 
716   if (dhBits > 0)
717     printf("%s: OK (TLS: %d.%d, %s, %d DH bits)\n", server, tlsVersion / 10, tlsVersion % 10, cipherName, dhBits);
718   else
719     printf("%s: OK (TLS: %d.%d, %s)\n", server, tlsVersion / 10, tlsVersion % 10, cipherName);
720 
721   printf("    %s\n", creds_str);
722 
723   if (verbose)
724   {
725     httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipps", NULL, host, port, resource);
726     request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
727     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
728     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
729     ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
730 
731     response = cupsDoRequest(http, request, resource);
732 
733     for (attr = ippFirstAttribute(response); attr; attr = ippNextAttribute(response))
734     {
735       if (ippGetGroupTag(attr) != IPP_TAG_PRINTER)
736         continue;
737 
738       if ((name = ippGetName(attr)) == NULL)
739         continue;
740 
741       ippAttributeString(attr, value, sizeof(value));
742       printf("    %s=%s\n", name, value);
743     }
744 
745     ippDelete(response);
746     puts("");
747   }
748 
749   httpClose(http);
750 
751   return (0);
752 }
753 
754 
755 /*
756  * 'usage()' - Show program usage.
757  */
758 
759 static void
usage(void)760 usage(void)
761 {
762   puts("Usage: ./tlscheck [options] server [port]");
763   puts("       ./tlscheck [options] ipps://server[:port]/path");
764   puts("");
765   puts("Options:");
766   puts("  --dh        Allow DH/DHE key exchange");
767   puts("  --no-cbc    Disable CBC cipher suites");
768   puts("  --no-tls10  Disable TLS/1.0");
769   puts("  --rc4       Allow RC4 encryption");
770   puts("  --tls10     Only use TLS/1.0");
771   puts("  --tls11     Only use TLS/1.1");
772   puts("  --tls12     Only use TLS/1.2");
773   puts("  --tls13     Only use TLS/1.3");
774   puts("  --verbose   Be verbose");
775   puts("  -4          Connect using IPv4 addresses only");
776   puts("  -6          Connect using IPv6 addresses only");
777   puts("  -v          Be verbose");
778   puts("");
779   puts("The default port is 631.");
780 
781   exit(1);
782 }
783 #endif /* !HAVE_SSL */
784