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