Line | Count | Source |
1 | | /* |
2 | | * User, system, and password routines 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 | | #include <stdlib.h> |
22 | | #include <sys/stat.h> |
23 | | #ifdef _WIN32 |
24 | | # include <windows.h> |
25 | | #else |
26 | | # include <pwd.h> |
27 | | # include <termios.h> |
28 | | # include <sys/utsname.h> |
29 | | #endif /* _WIN32 */ |
30 | | |
31 | | |
32 | | /* |
33 | | * Local constants... |
34 | | */ |
35 | | |
36 | | #ifdef __APPLE__ |
37 | | # define kCUPSPrintingPrefs CFSTR("org.cups.PrintingPrefs") |
38 | | # define kAllowAnyRootKey CFSTR("AllowAnyRoot") |
39 | | # define kAllowExpiredCertsKey CFSTR("AllowExpiredCerts") |
40 | | # define kEncryptionKey CFSTR("Encryption") |
41 | | # define kGSSServiceNameKey CFSTR("GSSServiceName") |
42 | | # define kSSLOptionsKey CFSTR("SSLOptions") |
43 | | # define kTrustOnFirstUseKey CFSTR("TrustOnFirstUse") |
44 | | # define kValidateCertsKey CFSTR("ValidateCerts") |
45 | | #endif /* __APPLE__ */ |
46 | | |
47 | 0 | #define _CUPS_PASSCHAR '*' /* Character that is echoed for password */ |
48 | | |
49 | | |
50 | | /* |
51 | | * Local types... |
52 | | */ |
53 | | |
54 | | typedef struct _cups_client_conf_s /**** client.conf config data ****/ |
55 | | { |
56 | | #ifdef HAVE_SSL |
57 | | int ssl_options, /* SSLOptions values */ |
58 | | ssl_min_version,/* Minimum SSL/TLS version */ |
59 | | ssl_max_version;/* Maximum SSL/TLS version */ |
60 | | #endif /* HAVE_SSL */ |
61 | | int trust_first, /* Trust on first use? */ |
62 | | any_root, /* Allow any (e.g., self-signed) root */ |
63 | | expired_certs, /* Allow expired certs */ |
64 | | validate_certs; /* Validate certificates */ |
65 | | http_encryption_t encryption; /* Encryption setting */ |
66 | | char user[65], /* User name */ |
67 | | server_name[256]; |
68 | | /* Server hostname */ |
69 | | #ifdef HAVE_GSSAPI |
70 | | char gss_service_name[32]; |
71 | | /* Kerberos service name */ |
72 | | #endif /* HAVE_GSSAPI */ |
73 | | } _cups_client_conf_t; |
74 | | |
75 | | |
76 | | /* |
77 | | * Local functions... |
78 | | */ |
79 | | |
80 | | #ifdef __APPLE__ |
81 | | static int cups_apple_get_boolean(CFStringRef key, int *value); |
82 | | static int cups_apple_get_string(CFStringRef key, char *value, size_t valsize); |
83 | | #endif /* __APPLE__ */ |
84 | | static int cups_boolean_value(const char *value); |
85 | | static void cups_finalize_client_conf(_cups_client_conf_t *cc); |
86 | | static void cups_init_client_conf(_cups_client_conf_t *cc); |
87 | | static void cups_read_client_conf(cups_file_t *fp, _cups_client_conf_t *cc); |
88 | | static void cups_set_default_ipp_port(_cups_globals_t *cg); |
89 | | static void cups_set_encryption(_cups_client_conf_t *cc, const char *value); |
90 | | #ifdef HAVE_GSSAPI |
91 | | static void cups_set_gss_service_name(_cups_client_conf_t *cc, const char *value); |
92 | | #endif /* HAVE_GSSAPI */ |
93 | | static void cups_set_server_name(_cups_client_conf_t *cc, const char *value); |
94 | | #ifdef HAVE_SSL |
95 | | static void cups_set_ssl_options(_cups_client_conf_t *cc, const char *value); |
96 | | #endif /* HAVE_SSL */ |
97 | | static void cups_set_user(_cups_client_conf_t *cc, const char *value); |
98 | | |
99 | | |
100 | | /* |
101 | | * 'cupsEncryption()' - Get the current encryption settings. |
102 | | * |
103 | | * The default encryption setting comes from the CUPS_ENCRYPTION |
104 | | * environment variable, then the ~/.cups/client.conf file, and finally the |
105 | | * /etc/cups/client.conf file. If not set, the default is |
106 | | * @code HTTP_ENCRYPTION_IF_REQUESTED@. |
107 | | * |
108 | | * Note: The current encryption setting is tracked separately for each thread |
109 | | * in a program. Multi-threaded programs that override the setting via the |
110 | | * @link cupsSetEncryption@ function need to do so in each thread for the same |
111 | | * setting to be used. |
112 | | */ |
113 | | |
114 | | http_encryption_t /* O - Encryption settings */ |
115 | | cupsEncryption(void) |
116 | 0 | { |
117 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
118 | | |
119 | |
|
120 | 0 | if (cg->encryption == (http_encryption_t)-1) |
121 | 0 | _cupsSetDefaults(); |
122 | |
|
123 | 0 | return (cg->encryption); |
124 | 0 | } |
125 | | |
126 | | |
127 | | /* |
128 | | * 'cupsGetPassword()' - Get a password from the user. |
129 | | * |
130 | | * Uses the current password callback function. Returns @code NULL@ if the |
131 | | * user does not provide a password. |
132 | | * |
133 | | * Note: The current password callback function is tracked separately for each |
134 | | * thread in a program. Multi-threaded programs that override the setting via |
135 | | * the @link cupsSetPasswordCB@ or @link cupsSetPasswordCB2@ functions need to |
136 | | * do so in each thread for the same function to be used. |
137 | | * |
138 | | * @exclude all@ |
139 | | */ |
140 | | |
141 | | const char * /* O - Password */ |
142 | | cupsGetPassword(const char *prompt) /* I - Prompt string */ |
143 | 0 | { |
144 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
145 | | |
146 | |
|
147 | 0 | return ((cg->password_cb)(prompt, NULL, NULL, NULL, cg->password_data)); |
148 | 0 | } |
149 | | |
150 | | |
151 | | /* |
152 | | * 'cupsGetPassword2()' - Get a password from the user using the current |
153 | | * password callback. |
154 | | * |
155 | | * Uses the current password callback function. Returns @code NULL@ if the |
156 | | * user does not provide a password. |
157 | | * |
158 | | * Note: The current password callback function is tracked separately for each |
159 | | * thread in a program. Multi-threaded programs that override the setting via |
160 | | * the @link cupsSetPasswordCB2@ function need to do so in each thread for the |
161 | | * same function to be used. |
162 | | * |
163 | | * @since CUPS 1.4/macOS 10.6@ |
164 | | */ |
165 | | |
166 | | const char * /* O - Password */ |
167 | | cupsGetPassword2(const char *prompt, /* I - Prompt string */ |
168 | | http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ |
169 | | const char *method, /* I - Request method ("GET", "POST", "PUT") */ |
170 | | const char *resource) /* I - Resource path */ |
171 | 0 | { |
172 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
173 | | |
174 | |
|
175 | 0 | if (!http) |
176 | 0 | http = _cupsConnect(); |
177 | |
|
178 | 0 | return ((cg->password_cb)(prompt, http, method, resource, cg->password_data)); |
179 | 0 | } |
180 | | |
181 | | |
182 | | /* |
183 | | * 'cupsServer()' - Return the hostname/address of the current server. |
184 | | * |
185 | | * The default server comes from the CUPS_SERVER environment variable, then the |
186 | | * ~/.cups/client.conf file, and finally the /etc/cups/client.conf file. If not |
187 | | * set, the default is the local system - either "localhost" or a domain socket |
188 | | * path. |
189 | | * |
190 | | * The returned value can be a fully-qualified hostname, a numeric IPv4 or IPv6 |
191 | | * address, or a domain socket pathname. |
192 | | * |
193 | | * Note: The current server is tracked separately for each thread in a program. |
194 | | * Multi-threaded programs that override the server via the |
195 | | * @link cupsSetServer@ function need to do so in each thread for the same |
196 | | * server to be used. |
197 | | */ |
198 | | |
199 | | const char * /* O - Server name */ |
200 | | cupsServer(void) |
201 | 0 | { |
202 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
203 | | |
204 | |
|
205 | 0 | if (!cg->server[0]) |
206 | 0 | _cupsSetDefaults(); |
207 | |
|
208 | 0 | return (cg->server); |
209 | 0 | } |
210 | | |
211 | | |
212 | | /* |
213 | | * 'cupsSetClientCertCB()' - Set the client certificate callback. |
214 | | * |
215 | | * Pass @code NULL@ to restore the default callback. |
216 | | * |
217 | | * Note: The current certificate callback is tracked separately for each thread |
218 | | * in a program. Multi-threaded programs that override the callback need to do |
219 | | * so in each thread for the same callback to be used. |
220 | | * |
221 | | * @since CUPS 1.5/macOS 10.7@ |
222 | | */ |
223 | | |
224 | | void |
225 | | cupsSetClientCertCB( |
226 | | cups_client_cert_cb_t cb, /* I - Callback function */ |
227 | | void *user_data) /* I - User data pointer */ |
228 | 0 | { |
229 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
230 | | |
231 | |
|
232 | 0 | cg->client_cert_cb = cb; |
233 | 0 | cg->client_cert_data = user_data; |
234 | 0 | } |
235 | | |
236 | | |
237 | | /* |
238 | | * 'cupsSetCredentials()' - Set the default credentials to be used for SSL/TLS |
239 | | * connections. |
240 | | * |
241 | | * Note: The default credentials are tracked separately for each thread in a |
242 | | * program. Multi-threaded programs that override the setting need to do so in |
243 | | * each thread for the same setting to be used. |
244 | | * |
245 | | * @since CUPS 1.5/macOS 10.7@ |
246 | | */ |
247 | | |
248 | | int /* O - Status of call (0 = success) */ |
249 | | cupsSetCredentials( |
250 | | cups_array_t *credentials) /* I - Array of credentials */ |
251 | 0 | { |
252 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
253 | | |
254 | |
|
255 | 0 | if (cupsArrayCount(credentials) < 1) |
256 | 0 | return (-1); |
257 | | |
258 | | #ifdef HAVE_SSL |
259 | | _httpFreeCredentials(cg->tls_credentials); |
260 | | cg->tls_credentials = _httpCreateCredentials(credentials); |
261 | | #endif /* HAVE_SSL */ |
262 | | |
263 | 0 | return (cg->tls_credentials ? 0 : -1); |
264 | 0 | } |
265 | | |
266 | | |
267 | | /* |
268 | | * 'cupsSetEncryption()' - Set the encryption preference. |
269 | | * |
270 | | * The default encryption setting comes from the CUPS_ENCRYPTION |
271 | | * environment variable, then the ~/.cups/client.conf file, and finally the |
272 | | * /etc/cups/client.conf file. If not set, the default is |
273 | | * @code HTTP_ENCRYPTION_IF_REQUESTED@. |
274 | | * |
275 | | * Note: The current encryption setting is tracked separately for each thread |
276 | | * in a program. Multi-threaded programs that override the setting need to do |
277 | | * so in each thread for the same setting to be used. |
278 | | */ |
279 | | |
280 | | void |
281 | | cupsSetEncryption(http_encryption_t e) /* I - New encryption preference */ |
282 | 0 | { |
283 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
284 | | |
285 | |
|
286 | 0 | cg->encryption = e; |
287 | |
|
288 | 0 | if (cg->http) |
289 | 0 | httpEncryption(cg->http, e); |
290 | 0 | } |
291 | | |
292 | | |
293 | | /* |
294 | | * 'cupsSetPasswordCB()' - Set the password callback for CUPS. |
295 | | * |
296 | | * Pass @code NULL@ to restore the default (console) password callback, which |
297 | | * reads the password from the console. Programs should call either this |
298 | | * function or @link cupsSetPasswordCB2@, as only one callback can be registered |
299 | | * by a program per thread. |
300 | | * |
301 | | * Note: The current password callback is tracked separately for each thread |
302 | | * in a program. Multi-threaded programs that override the callback need to do |
303 | | * so in each thread for the same callback to be used. |
304 | | * |
305 | | * @exclude all@ |
306 | | */ |
307 | | |
308 | | void |
309 | | cupsSetPasswordCB(cups_password_cb_t cb)/* I - Callback function */ |
310 | 0 | { |
311 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
312 | | |
313 | |
|
314 | 0 | if (cb == (cups_password_cb_t)0) |
315 | 0 | cg->password_cb = (cups_password_cb2_t)_cupsGetPassword; |
316 | 0 | else |
317 | 0 | cg->password_cb = (cups_password_cb2_t)cb; |
318 | |
|
319 | 0 | cg->password_data = NULL; |
320 | 0 | } |
321 | | |
322 | | |
323 | | /* |
324 | | * 'cupsSetPasswordCB2()' - Set the advanced password callback for CUPS. |
325 | | * |
326 | | * Pass @code NULL@ to restore the default (console) password callback, which |
327 | | * reads the password from the console. Programs should call either this |
328 | | * function or @link cupsSetPasswordCB2@, as only one callback can be registered |
329 | | * by a program per thread. |
330 | | * |
331 | | * Note: The current password callback is tracked separately for each thread |
332 | | * in a program. Multi-threaded programs that override the callback need to do |
333 | | * so in each thread for the same callback to be used. |
334 | | * |
335 | | * @since CUPS 1.4/macOS 10.6@ |
336 | | */ |
337 | | |
338 | | void |
339 | | cupsSetPasswordCB2( |
340 | | cups_password_cb2_t cb, /* I - Callback function */ |
341 | | void *user_data) /* I - User data pointer */ |
342 | 0 | { |
343 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
344 | | |
345 | |
|
346 | 0 | if (cb == (cups_password_cb2_t)0) |
347 | 0 | cg->password_cb = (cups_password_cb2_t)_cupsGetPassword; |
348 | 0 | else |
349 | 0 | cg->password_cb = cb; |
350 | |
|
351 | 0 | cg->password_data = user_data; |
352 | 0 | } |
353 | | |
354 | | |
355 | | /* |
356 | | * 'cupsSetServer()' - Set the default server name and port. |
357 | | * |
358 | | * The "server" string can be a fully-qualified hostname, a numeric |
359 | | * IPv4 or IPv6 address, or a domain socket pathname. Hostnames and numeric IP |
360 | | * addresses can be optionally followed by a colon and port number to override |
361 | | * the default port 631, e.g. "hostname:8631". Pass @code NULL@ to restore the |
362 | | * default server name and port. |
363 | | * |
364 | | * Note: The current server is tracked separately for each thread in a program. |
365 | | * Multi-threaded programs that override the server need to do so in each |
366 | | * thread for the same server to be used. |
367 | | */ |
368 | | |
369 | | void |
370 | | cupsSetServer(const char *server) /* I - Server name */ |
371 | 0 | { |
372 | 0 | char *options, /* Options */ |
373 | 0 | *port; /* Pointer to port */ |
374 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
375 | | |
376 | |
|
377 | 0 | if (server) |
378 | 0 | { |
379 | 0 | strlcpy(cg->server, server, sizeof(cg->server)); |
380 | |
|
381 | 0 | if (cg->server[0] != '/' && (options = strrchr(cg->server, '/')) != NULL) |
382 | 0 | { |
383 | 0 | *options++ = '\0'; |
384 | |
|
385 | 0 | if (!strcmp(options, "version=1.0")) |
386 | 0 | cg->server_version = 10; |
387 | 0 | else if (!strcmp(options, "version=1.1")) |
388 | 0 | cg->server_version = 11; |
389 | 0 | else if (!strcmp(options, "version=2.0")) |
390 | 0 | cg->server_version = 20; |
391 | 0 | else if (!strcmp(options, "version=2.1")) |
392 | 0 | cg->server_version = 21; |
393 | 0 | else if (!strcmp(options, "version=2.2")) |
394 | 0 | cg->server_version = 22; |
395 | 0 | } |
396 | 0 | else |
397 | 0 | cg->server_version = 20; |
398 | |
|
399 | 0 | if (cg->server[0] != '/' && (port = strrchr(cg->server, ':')) != NULL && |
400 | 0 | !strchr(port, ']') && isdigit(port[1] & 255)) |
401 | 0 | { |
402 | 0 | *port++ = '\0'; |
403 | |
|
404 | 0 | cg->ipp_port = atoi(port); |
405 | 0 | } |
406 | |
|
407 | 0 | if (!cg->ipp_port) |
408 | 0 | cups_set_default_ipp_port(cg); |
409 | |
|
410 | 0 | if (cg->server[0] == '/') |
411 | 0 | strlcpy(cg->servername, "localhost", sizeof(cg->servername)); |
412 | 0 | else |
413 | 0 | strlcpy(cg->servername, cg->server, sizeof(cg->servername)); |
414 | 0 | } |
415 | 0 | else |
416 | 0 | { |
417 | 0 | cg->server[0] = '\0'; |
418 | 0 | cg->servername[0] = '\0'; |
419 | 0 | cg->server_version = 20; |
420 | 0 | cg->ipp_port = 0; |
421 | 0 | } |
422 | |
|
423 | 0 | if (cg->http) |
424 | 0 | { |
425 | 0 | httpClose(cg->http); |
426 | 0 | cg->http = NULL; |
427 | 0 | } |
428 | 0 | } |
429 | | |
430 | | |
431 | | /* |
432 | | * 'cupsSetServerCertCB()' - Set the server certificate callback. |
433 | | * |
434 | | * Pass @code NULL@ to restore the default callback. |
435 | | * |
436 | | * Note: The current credentials callback is tracked separately for each thread |
437 | | * in a program. Multi-threaded programs that override the callback need to do |
438 | | * so in each thread for the same callback to be used. |
439 | | * |
440 | | * @since CUPS 1.5/macOS 10.7@ |
441 | | */ |
442 | | |
443 | | void |
444 | | cupsSetServerCertCB( |
445 | | cups_server_cert_cb_t cb, /* I - Callback function */ |
446 | | void *user_data) /* I - User data pointer */ |
447 | 0 | { |
448 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
449 | | |
450 | |
|
451 | 0 | cg->server_cert_cb = cb; |
452 | 0 | cg->server_cert_data = user_data; |
453 | 0 | } |
454 | | |
455 | | |
456 | | /* |
457 | | * 'cupsSetUser()' - Set the default user name. |
458 | | * |
459 | | * Pass @code NULL@ to restore the default user name. |
460 | | * |
461 | | * Note: The current user name is tracked separately for each thread in a |
462 | | * program. Multi-threaded programs that override the user name need to do so |
463 | | * in each thread for the same user name to be used. |
464 | | */ |
465 | | |
466 | | void |
467 | | cupsSetUser(const char *user) /* I - User name */ |
468 | 0 | { |
469 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
470 | | |
471 | |
|
472 | 0 | if (user) |
473 | 0 | strlcpy(cg->user, user, sizeof(cg->user)); |
474 | 0 | else |
475 | 0 | cg->user[0] = '\0'; |
476 | 0 | } |
477 | | |
478 | | |
479 | | /* |
480 | | * 'cupsSetUserAgent()' - Set the default HTTP User-Agent string. |
481 | | * |
482 | | * Setting the string to NULL forces the default value containing the CUPS |
483 | | * version, IPP version, and operating system version and architecture. |
484 | | * |
485 | | * @since CUPS 1.7/macOS 10.9@ |
486 | | */ |
487 | | |
488 | | void |
489 | | cupsSetUserAgent(const char *user_agent)/* I - User-Agent string or @code NULL@ */ |
490 | 0 | { |
491 | 0 | _cups_globals_t *cg = _cupsGlobals(); |
492 | | /* Thread globals */ |
493 | | #ifdef _WIN32 |
494 | | SYSTEM_INFO sysinfo; /* System information */ |
495 | | OSVERSIONINFO version; /* OS version info */ |
496 | | #else |
497 | 0 | struct utsname name; /* uname info */ |
498 | 0 | #endif /* _WIN32 */ |
499 | | |
500 | |
|
501 | 0 | if (user_agent) |
502 | 0 | { |
503 | 0 | strlcpy(cg->user_agent, user_agent, sizeof(cg->user_agent)); |
504 | 0 | return; |
505 | 0 | } |
506 | | |
507 | | #ifdef _WIN32 |
508 | | version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
509 | | GetVersionEx(&version); |
510 | | GetNativeSystemInfo(&sysinfo); |
511 | | |
512 | | snprintf(cg->user_agent, sizeof(cg->user_agent), |
513 | | CUPS_MINIMAL " (Windows %d.%d; %s) IPP/2.0", |
514 | | version.dwMajorVersion, version.dwMinorVersion, |
515 | | sysinfo.wProcessorArchitecture |
516 | | == PROCESSOR_ARCHITECTURE_AMD64 ? "amd64" : |
517 | | sysinfo.wProcessorArchitecture |
518 | | == PROCESSOR_ARCHITECTURE_ARM ? "arm" : |
519 | | sysinfo.wProcessorArchitecture |
520 | | == PROCESSOR_ARCHITECTURE_IA64 ? "ia64" : |
521 | | sysinfo.wProcessorArchitecture |
522 | | == PROCESSOR_ARCHITECTURE_INTEL ? "intel" : |
523 | | "unknown"); |
524 | | |
525 | | #else |
526 | 0 | uname(&name); |
527 | |
|
528 | 0 | snprintf(cg->user_agent, sizeof(cg->user_agent), |
529 | 0 | CUPS_MINIMAL " (%s %s; %s) IPP/2.0", |
530 | 0 | name.sysname, name.release, name.machine); |
531 | 0 | #endif /* _WIN32 */ |
532 | 0 | } |
533 | | |
534 | | |
535 | | /* |
536 | | * 'cupsUser()' - Return the current user's name. |
537 | | * |
538 | | * Note: The current user name is tracked separately for each thread in a |
539 | | * program. Multi-threaded programs that override the user name with the |
540 | | * @link cupsSetUser@ function need to do so in each thread for the same user |
541 | | * name to be used. |
542 | | */ |
543 | | |
544 | | const char * /* O - User name */ |
545 | | cupsUser(void) |
546 | 0 | { |
547 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
548 | | |
549 | |
|
550 | 0 | if (!cg->user[0]) |
551 | 0 | _cupsSetDefaults(); |
552 | |
|
553 | 0 | return (cg->user); |
554 | 0 | } |
555 | | |
556 | | |
557 | | /* |
558 | | * 'cupsUserAgent()' - Return the default HTTP User-Agent string. |
559 | | * |
560 | | * @since CUPS 1.7/macOS 10.9@ |
561 | | */ |
562 | | |
563 | | const char * /* O - User-Agent string */ |
564 | | cupsUserAgent(void) |
565 | 0 | { |
566 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Thread globals */ |
567 | | |
568 | |
|
569 | 0 | if (!cg->user_agent[0]) |
570 | 0 | cupsSetUserAgent(NULL); |
571 | |
|
572 | 0 | return (cg->user_agent); |
573 | 0 | } |
574 | | |
575 | | |
576 | | /* |
577 | | * '_cupsGetPassword()' - Get a password from the user. |
578 | | */ |
579 | | |
580 | | const char * /* O - Password or @code NULL@ if none */ |
581 | | _cupsGetPassword(const char *prompt) /* I - Prompt string */ |
582 | 0 | { |
583 | | #ifdef _WIN32 |
584 | | HANDLE tty; /* Console handle */ |
585 | | DWORD mode; /* Console mode */ |
586 | | char passch, /* Current key press */ |
587 | | *passptr, /* Pointer into password string */ |
588 | | *passend; /* End of password string */ |
589 | | DWORD passbytes; /* Bytes read */ |
590 | | _cups_globals_t *cg = _cupsGlobals(); |
591 | | /* Thread globals */ |
592 | | |
593 | | |
594 | | /* |
595 | | * Disable input echo and set raw input... |
596 | | */ |
597 | | |
598 | | if ((tty = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) |
599 | | return (NULL); |
600 | | |
601 | | if (!GetConsoleMode(tty, &mode)) |
602 | | return (NULL); |
603 | | |
604 | | if (!SetConsoleMode(tty, 0)) |
605 | | return (NULL); |
606 | | |
607 | | /* |
608 | | * Display the prompt... |
609 | | */ |
610 | | |
611 | | printf("%s ", prompt); |
612 | | fflush(stdout); |
613 | | |
614 | | /* |
615 | | * Read the password string from /dev/tty until we get interrupted or get a |
616 | | * carriage return or newline... |
617 | | */ |
618 | | |
619 | | passptr = cg->password; |
620 | | passend = cg->password + sizeof(cg->password) - 1; |
621 | | |
622 | | while (ReadFile(tty, &passch, 1, &passbytes, NULL)) |
623 | | { |
624 | | if (passch == 0x0A || passch == 0x0D) |
625 | | { |
626 | | /* |
627 | | * Enter/return... |
628 | | */ |
629 | | |
630 | | break; |
631 | | } |
632 | | else if (passch == 0x08 || passch == 0x7F) |
633 | | { |
634 | | /* |
635 | | * Backspace/delete (erase character)... |
636 | | */ |
637 | | |
638 | | if (passptr > cg->password) |
639 | | { |
640 | | passptr --; |
641 | | fputs("\010 \010", stdout); |
642 | | } |
643 | | else |
644 | | putchar(0x07); |
645 | | } |
646 | | else if (passch == 0x15) |
647 | | { |
648 | | /* |
649 | | * CTRL+U (erase line) |
650 | | */ |
651 | | |
652 | | if (passptr > cg->password) |
653 | | { |
654 | | while (passptr > cg->password) |
655 | | { |
656 | | passptr --; |
657 | | fputs("\010 \010", stdout); |
658 | | } |
659 | | } |
660 | | else |
661 | | putchar(0x07); |
662 | | } |
663 | | else if (passch == 0x03) |
664 | | { |
665 | | /* |
666 | | * CTRL+C... |
667 | | */ |
668 | | |
669 | | passptr = cg->password; |
670 | | break; |
671 | | } |
672 | | else if ((passch & 255) < 0x20 || passptr >= passend) |
673 | | putchar(0x07); |
674 | | else |
675 | | { |
676 | | *passptr++ = passch; |
677 | | putchar(_CUPS_PASSCHAR); |
678 | | } |
679 | | |
680 | | fflush(stdout); |
681 | | } |
682 | | |
683 | | putchar('\n'); |
684 | | fflush(stdout); |
685 | | |
686 | | /* |
687 | | * Cleanup... |
688 | | */ |
689 | | |
690 | | SetConsoleMode(tty, mode); |
691 | | |
692 | | /* |
693 | | * Return the proper value... |
694 | | */ |
695 | | |
696 | | if (passbytes == 1 && passptr > cg->password) |
697 | | { |
698 | | *passptr = '\0'; |
699 | | return (cg->password); |
700 | | } |
701 | | else |
702 | | { |
703 | | memset(cg->password, 0, sizeof(cg->password)); |
704 | | return (NULL); |
705 | | } |
706 | | |
707 | | #else |
708 | 0 | int tty; /* /dev/tty - never read from stdin */ |
709 | 0 | struct termios original, /* Original input mode */ |
710 | 0 | noecho; /* No echo input mode */ |
711 | 0 | char passch, /* Current key press */ |
712 | 0 | *passptr, /* Pointer into password string */ |
713 | 0 | *passend; /* End of password string */ |
714 | 0 | ssize_t passbytes; /* Bytes read */ |
715 | 0 | _cups_globals_t *cg = _cupsGlobals(); |
716 | | /* Thread globals */ |
717 | | |
718 | | |
719 | | /* |
720 | | * Disable input echo and set raw input... |
721 | | */ |
722 | |
|
723 | 0 | if ((tty = open("/dev/tty", O_RDONLY)) < 0) |
724 | 0 | return (NULL); |
725 | | |
726 | 0 | if (tcgetattr(tty, &original)) |
727 | 0 | { |
728 | 0 | close(tty); |
729 | 0 | return (NULL); |
730 | 0 | } |
731 | | |
732 | 0 | noecho = original; |
733 | 0 | noecho.c_lflag &= (tcflag_t)~(ICANON | ECHO | ECHOE | ISIG); |
734 | 0 | noecho.c_cc[VMIN] = 1; |
735 | 0 | noecho.c_cc[VTIME] = 0; |
736 | |
|
737 | 0 | if (tcsetattr(tty, TCSAFLUSH, &noecho)) |
738 | 0 | { |
739 | 0 | close(tty); |
740 | 0 | return (NULL); |
741 | 0 | } |
742 | | |
743 | | /* |
744 | | * Display the prompt... |
745 | | */ |
746 | | |
747 | 0 | printf("%s ", prompt); |
748 | 0 | fflush(stdout); |
749 | | |
750 | | /* |
751 | | * Read the password string from /dev/tty until we get interrupted or get a |
752 | | * carriage return or newline... |
753 | | */ |
754 | |
|
755 | 0 | passptr = cg->password; |
756 | 0 | passend = cg->password + sizeof(cg->password) - 1; |
757 | |
|
758 | 0 | while ((passbytes = read(tty, &passch, 1)) == 1) |
759 | 0 | { |
760 | 0 | if (passch == noecho.c_cc[VEOL] || |
761 | 0 | # ifdef VEOL2 |
762 | 0 | passch == noecho.c_cc[VEOL2] || |
763 | 0 | # endif /* VEOL2 */ |
764 | 0 | passch == 0x0A || passch == 0x0D) |
765 | 0 | { |
766 | | /* |
767 | | * Enter/return... |
768 | | */ |
769 | |
|
770 | 0 | break; |
771 | 0 | } |
772 | 0 | else if (passch == noecho.c_cc[VERASE] || |
773 | 0 | passch == 0x08 || passch == 0x7F) |
774 | 0 | { |
775 | | /* |
776 | | * Backspace/delete (erase character)... |
777 | | */ |
778 | |
|
779 | 0 | if (passptr > cg->password) |
780 | 0 | { |
781 | 0 | passptr --; |
782 | 0 | fputs("\010 \010", stdout); |
783 | 0 | } |
784 | 0 | else |
785 | 0 | putchar(0x07); |
786 | 0 | } |
787 | 0 | else if (passch == noecho.c_cc[VKILL]) |
788 | 0 | { |
789 | | /* |
790 | | * CTRL+U (erase line) |
791 | | */ |
792 | |
|
793 | 0 | if (passptr > cg->password) |
794 | 0 | { |
795 | 0 | while (passptr > cg->password) |
796 | 0 | { |
797 | 0 | passptr --; |
798 | 0 | fputs("\010 \010", stdout); |
799 | 0 | } |
800 | 0 | } |
801 | 0 | else |
802 | 0 | putchar(0x07); |
803 | 0 | } |
804 | 0 | else if (passch == noecho.c_cc[VINTR] || passch == noecho.c_cc[VQUIT] || |
805 | 0 | passch == noecho.c_cc[VEOF]) |
806 | 0 | { |
807 | | /* |
808 | | * CTRL+C, CTRL+D, or CTRL+Z... |
809 | | */ |
810 | |
|
811 | 0 | passptr = cg->password; |
812 | 0 | break; |
813 | 0 | } |
814 | 0 | else if ((passch & 255) < 0x20 || passptr >= passend) |
815 | 0 | putchar(0x07); |
816 | 0 | else |
817 | 0 | { |
818 | 0 | *passptr++ = passch; |
819 | 0 | putchar(_CUPS_PASSCHAR); |
820 | 0 | } |
821 | | |
822 | 0 | fflush(stdout); |
823 | 0 | } |
824 | |
|
825 | 0 | putchar('\n'); |
826 | 0 | fflush(stdout); |
827 | | |
828 | | /* |
829 | | * Cleanup... |
830 | | */ |
831 | |
|
832 | 0 | tcsetattr(tty, TCSAFLUSH, &original); |
833 | 0 | close(tty); |
834 | | |
835 | | /* |
836 | | * Return the proper value... |
837 | | */ |
838 | |
|
839 | 0 | if (passbytes == 1 && passptr > cg->password) |
840 | 0 | { |
841 | 0 | *passptr = '\0'; |
842 | 0 | return (cg->password); |
843 | 0 | } |
844 | 0 | else |
845 | 0 | { |
846 | 0 | memset(cg->password, 0, sizeof(cg->password)); |
847 | 0 | return (NULL); |
848 | 0 | } |
849 | 0 | #endif /* _WIN32 */ |
850 | 0 | } |
851 | | |
852 | | |
853 | | #ifdef HAVE_GSSAPI |
854 | | /* |
855 | | * '_cupsGSSServiceName()' - Get the GSS (Kerberos) service name. |
856 | | */ |
857 | | |
858 | | const char * |
859 | | _cupsGSSServiceName(void) |
860 | | { |
861 | | _cups_globals_t *cg = _cupsGlobals(); /* Thread globals */ |
862 | | |
863 | | |
864 | | if (!cg->gss_service_name[0]) |
865 | | _cupsSetDefaults(); |
866 | | |
867 | | return (cg->gss_service_name); |
868 | | } |
869 | | #endif /* HAVE_GSSAPI */ |
870 | | |
871 | | |
872 | | /* |
873 | | * '_cupsSetDefaults()' - Set the default server, port, and encryption. |
874 | | */ |
875 | | |
876 | | void |
877 | | _cupsSetDefaults(void) |
878 | 0 | { |
879 | 0 | cups_file_t *fp; /* File */ |
880 | 0 | const char *home; /* Home directory of user */ |
881 | 0 | char filename[1024]; /* Filename */ |
882 | 0 | _cups_client_conf_t cc; /* client.conf values */ |
883 | 0 | _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ |
884 | | |
885 | |
|
886 | 0 | DEBUG_puts("_cupsSetDefaults()"); |
887 | | |
888 | | /* |
889 | | * Load initial client.conf values... |
890 | | */ |
891 | |
|
892 | 0 | cups_init_client_conf(&cc); |
893 | | |
894 | | /* |
895 | | * Read the /etc/cups/client.conf and ~/.cups/client.conf files, if |
896 | | * present. |
897 | | */ |
898 | |
|
899 | 0 | snprintf(filename, sizeof(filename), "%s/client.conf", cg->cups_serverroot); |
900 | 0 | if ((fp = cupsFileOpen(filename, "r")) != NULL) |
901 | 0 | { |
902 | 0 | cups_read_client_conf(fp, &cc); |
903 | 0 | cupsFileClose(fp); |
904 | 0 | } |
905 | |
|
906 | 0 | # ifdef HAVE_GETEUID |
907 | 0 | if ((geteuid() == getuid() || !getuid()) && getegid() == getgid() && (home = getenv("HOME")) != NULL) |
908 | | # elif !defined(_WIN32) |
909 | | if (getuid() && (home = getenv("HOME")) != NULL) |
910 | | # else |
911 | | if ((home = getenv("HOME")) != NULL) |
912 | | # endif /* HAVE_GETEUID */ |
913 | 0 | { |
914 | | /* |
915 | | * Look for ~/.cups/client.conf... |
916 | | */ |
917 | |
|
918 | 0 | snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home); |
919 | 0 | if ((fp = cupsFileOpen(filename, "r")) != NULL) |
920 | 0 | { |
921 | 0 | cups_read_client_conf(fp, &cc); |
922 | 0 | cupsFileClose(fp); |
923 | 0 | } |
924 | 0 | } |
925 | | |
926 | | /* |
927 | | * Finalize things so every client.conf value is set... |
928 | | */ |
929 | |
|
930 | 0 | cups_finalize_client_conf(&cc); |
931 | |
|
932 | 0 | if (cg->encryption == (http_encryption_t)-1) |
933 | 0 | cg->encryption = cc.encryption; |
934 | |
|
935 | 0 | if (!cg->server[0] || !cg->ipp_port) |
936 | 0 | cupsSetServer(cc.server_name); |
937 | |
|
938 | 0 | if (!cg->ipp_port) |
939 | 0 | cups_set_default_ipp_port(cg); |
940 | |
|
941 | 0 | if (!cg->user[0]) |
942 | 0 | strlcpy(cg->user, cc.user, sizeof(cg->user)); |
943 | |
|
944 | | #ifdef HAVE_GSSAPI |
945 | | if (!cg->gss_service_name[0]) |
946 | | strlcpy(cg->gss_service_name, cc.gss_service_name, sizeof(cg->gss_service_name)); |
947 | | #endif /* HAVE_GSSAPI */ |
948 | |
|
949 | 0 | if (cg->trust_first < 0) |
950 | 0 | cg->trust_first = cc.trust_first; |
951 | |
|
952 | 0 | if (cg->any_root < 0) |
953 | 0 | cg->any_root = cc.any_root; |
954 | |
|
955 | 0 | if (cg->expired_certs < 0) |
956 | 0 | cg->expired_certs = cc.expired_certs; |
957 | |
|
958 | 0 | if (cg->validate_certs < 0) |
959 | 0 | cg->validate_certs = cc.validate_certs; |
960 | |
|
961 | | #ifdef HAVE_SSL |
962 | | _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT, cc.ssl_min_version, cc.ssl_max_version); |
963 | | #endif /* HAVE_SSL */ |
964 | 0 | } |
965 | | |
966 | | |
967 | | #ifdef __APPLE__ |
968 | | /* |
969 | | * 'cups_apple_get_boolean()' - Get a boolean setting from the CUPS preferences. |
970 | | */ |
971 | | |
972 | | static int /* O - 1 if set, 0 otherwise */ |
973 | | cups_apple_get_boolean( |
974 | | CFStringRef key, /* I - Key (name) */ |
975 | | int *value) /* O - Boolean value */ |
976 | | { |
977 | | Boolean bval, /* Preference value */ |
978 | | bval_set; /* Value is set? */ |
979 | | |
980 | | |
981 | | bval = CFPreferencesGetAppBooleanValue(key, kCUPSPrintingPrefs, &bval_set); |
982 | | |
983 | | if (bval_set) |
984 | | *value = (int)bval; |
985 | | |
986 | | return ((int)bval_set); |
987 | | } |
988 | | |
989 | | |
990 | | /* |
991 | | * 'cups_apple_get_string()' - Get a string setting from the CUPS preferences. |
992 | | */ |
993 | | |
994 | | static int /* O - 1 if set, 0 otherwise */ |
995 | | cups_apple_get_string( |
996 | | CFStringRef key, /* I - Key (name) */ |
997 | | char *value, /* O - String value */ |
998 | | size_t valsize) /* I - Size of value buffer */ |
999 | | { |
1000 | | CFStringRef sval; /* String value */ |
1001 | | |
1002 | | |
1003 | | if ((sval = CFPreferencesCopyAppValue(key, kCUPSPrintingPrefs)) != NULL) |
1004 | | { |
1005 | | Boolean result = CFStringGetCString(sval, value, (CFIndex)valsize, kCFStringEncodingUTF8); |
1006 | | |
1007 | | CFRelease(sval); |
1008 | | |
1009 | | if (result) |
1010 | | return (1); |
1011 | | } |
1012 | | |
1013 | | return (0); |
1014 | | } |
1015 | | #endif /* __APPLE__ */ |
1016 | | |
1017 | | |
1018 | | /* |
1019 | | * 'cups_boolean_value()' - Convert a string to a boolean value. |
1020 | | */ |
1021 | | |
1022 | | static int /* O - Boolean value */ |
1023 | | cups_boolean_value(const char *value) /* I - String value */ |
1024 | 0 | { |
1025 | 0 | return (!_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "true")); |
1026 | 0 | } |
1027 | | |
1028 | | |
1029 | | /* |
1030 | | * 'cups_finalize_client_conf()' - Finalize client.conf values. |
1031 | | */ |
1032 | | |
1033 | | static void |
1034 | | cups_finalize_client_conf( |
1035 | | _cups_client_conf_t *cc) /* I - client.conf values */ |
1036 | 0 | { |
1037 | 0 | const char *value; /* Environment variable */ |
1038 | | |
1039 | |
|
1040 | 0 | if ((value = getenv("CUPS_TRUSTFIRST")) != NULL) |
1041 | 0 | cc->trust_first = cups_boolean_value(value); |
1042 | |
|
1043 | 0 | if ((value = getenv("CUPS_ANYROOT")) != NULL) |
1044 | 0 | cc->any_root = cups_boolean_value(value); |
1045 | |
|
1046 | 0 | if ((value = getenv("CUPS_ENCRYPTION")) != NULL) |
1047 | 0 | cups_set_encryption(cc, value); |
1048 | |
|
1049 | 0 | if ((value = getenv("CUPS_EXPIREDCERTS")) != NULL) |
1050 | 0 | cc->expired_certs = cups_boolean_value(value); |
1051 | |
|
1052 | | #ifdef HAVE_GSSAPI |
1053 | | if ((value = getenv("CUPS_GSSSERVICENAME")) != NULL) |
1054 | | cups_set_gss_service_name(cc, value); |
1055 | | #endif /* HAVE_GSSAPI */ |
1056 | |
|
1057 | 0 | if ((value = getenv("CUPS_SERVER")) != NULL) |
1058 | 0 | cups_set_server_name(cc, value); |
1059 | |
|
1060 | 0 | if ((value = getenv("CUPS_USER")) != NULL) |
1061 | 0 | cups_set_user(cc, value); |
1062 | |
|
1063 | 0 | if ((value = getenv("CUPS_VALIDATECERTS")) != NULL) |
1064 | 0 | cc->validate_certs = cups_boolean_value(value); |
1065 | | |
1066 | | /* |
1067 | | * Then apply defaults for those values that haven't been set... |
1068 | | */ |
1069 | |
|
1070 | 0 | if (cc->trust_first < 0) |
1071 | 0 | cc->trust_first = 1; |
1072 | |
|
1073 | 0 | if (cc->any_root < 0) |
1074 | 0 | cc->any_root = 1; |
1075 | |
|
1076 | 0 | if (cc->encryption == (http_encryption_t)-1) |
1077 | 0 | cc->encryption = HTTP_ENCRYPTION_IF_REQUESTED; |
1078 | |
|
1079 | 0 | if (cc->expired_certs < 0) |
1080 | 0 | cc->expired_certs = 0; |
1081 | |
|
1082 | | #ifdef HAVE_GSSAPI |
1083 | | if (!cc->gss_service_name[0]) |
1084 | | cups_set_gss_service_name(cc, CUPS_DEFAULT_GSSSERVICENAME); |
1085 | | #endif /* HAVE_GSSAPI */ |
1086 | |
|
1087 | 0 | if (!cc->server_name[0]) |
1088 | 0 | { |
1089 | 0 | #ifdef CUPS_DEFAULT_DOMAINSOCKET |
1090 | | /* |
1091 | | * If we are compiled with domain socket support, only use the |
1092 | | * domain socket if it exists and has the right permissions... |
1093 | | */ |
1094 | |
|
1095 | 0 | if (!access(CUPS_DEFAULT_DOMAINSOCKET, R_OK)) |
1096 | 0 | cups_set_server_name(cc, CUPS_DEFAULT_DOMAINSOCKET); |
1097 | 0 | else |
1098 | 0 | #endif /* CUPS_DEFAULT_DOMAINSOCKET */ |
1099 | 0 | cups_set_server_name(cc, "localhost"); |
1100 | 0 | } |
1101 | |
|
1102 | 0 | if (!cc->user[0]) |
1103 | 0 | { |
1104 | | #ifdef _WIN32 |
1105 | | /* |
1106 | | * Get the current user name from the OS... |
1107 | | */ |
1108 | | |
1109 | | DWORD size; /* Size of string */ |
1110 | | |
1111 | | size = sizeof(cc->user); |
1112 | | if (!GetUserName(cc->user, &size)) |
1113 | | #else |
1114 | | /* |
1115 | | * Try the USER environment variable as the default username... |
1116 | | */ |
1117 | |
|
1118 | 0 | const char *envuser = getenv("USER"); |
1119 | | /* Default username */ |
1120 | 0 | struct passwd *pw = NULL; /* Account information */ |
1121 | |
|
1122 | 0 | if (envuser) |
1123 | 0 | { |
1124 | | /* |
1125 | | * Validate USER matches the current UID, otherwise don't allow it to |
1126 | | * override things... This makes sure that printing after doing su |
1127 | | * or sudo records the correct username. |
1128 | | */ |
1129 | |
|
1130 | 0 | if ((pw = getpwnam(envuser)) != NULL && pw->pw_uid != getuid()) |
1131 | 0 | pw = NULL; |
1132 | 0 | } |
1133 | |
|
1134 | 0 | if (!pw) |
1135 | 0 | pw = getpwuid(getuid()); |
1136 | |
|
1137 | 0 | if (pw) |
1138 | 0 | strlcpy(cc->user, pw->pw_name, sizeof(cc->user)); |
1139 | 0 | else |
1140 | 0 | #endif /* _WIN32 */ |
1141 | 0 | { |
1142 | | /* |
1143 | | * Use the default "unknown" user name... |
1144 | | */ |
1145 | |
|
1146 | 0 | strlcpy(cc->user, "unknown", sizeof(cc->user)); |
1147 | 0 | } |
1148 | 0 | } |
1149 | |
|
1150 | 0 | if (cc->validate_certs < 0) |
1151 | 0 | cc->validate_certs = 0; |
1152 | 0 | } |
1153 | | |
1154 | | |
1155 | | /* |
1156 | | * 'cups_init_client_conf()' - Initialize client.conf values. |
1157 | | */ |
1158 | | |
1159 | | static void |
1160 | | cups_init_client_conf( |
1161 | | _cups_client_conf_t *cc) /* I - client.conf values */ |
1162 | 0 | { |
1163 | | /* |
1164 | | * Clear all values to "not set"... |
1165 | | */ |
1166 | |
|
1167 | 0 | memset(cc, 0, sizeof(_cups_client_conf_t)); |
1168 | |
|
1169 | | #ifdef HAVE_SSL |
1170 | | cc->ssl_min_version = _HTTP_TLS_1_0; |
1171 | | cc->ssl_max_version = _HTTP_TLS_MAX; |
1172 | | #endif /* HAVE_SSL */ |
1173 | 0 | cc->encryption = (http_encryption_t)-1; |
1174 | 0 | cc->trust_first = -1; |
1175 | 0 | cc->any_root = -1; |
1176 | 0 | cc->expired_certs = -1; |
1177 | 0 | cc->validate_certs = -1; |
1178 | | |
1179 | | /* |
1180 | | * Load settings from the org.cups.PrintingPrefs plist (which trump |
1181 | | * everything...) |
1182 | | */ |
1183 | |
|
1184 | | #if defined(__APPLE__) && defined(HAVE_SSL) |
1185 | | char sval[1024]; /* String value */ |
1186 | | int bval; /* Boolean value */ |
1187 | | |
1188 | | if (cups_apple_get_boolean(kAllowAnyRootKey, &bval)) |
1189 | | cc->any_root = bval; |
1190 | | |
1191 | | if (cups_apple_get_boolean(kAllowExpiredCertsKey, &bval)) |
1192 | | cc->expired_certs = bval; |
1193 | | |
1194 | | if (cups_apple_get_string(kEncryptionKey, sval, sizeof(sval))) |
1195 | | cups_set_encryption(cc, sval); |
1196 | | |
1197 | | if (cups_apple_get_string(kSSLOptionsKey, sval, sizeof(sval))) |
1198 | | cups_set_ssl_options(cc, sval); |
1199 | | |
1200 | | if (cups_apple_get_boolean(kTrustOnFirstUseKey, &bval)) |
1201 | | cc->trust_first = bval; |
1202 | | |
1203 | | if (cups_apple_get_boolean(kValidateCertsKey, &bval)) |
1204 | | cc->validate_certs = bval; |
1205 | | #endif /* __APPLE__ && HAVE_SSL */ |
1206 | 0 | } |
1207 | | |
1208 | | |
1209 | | /* |
1210 | | * 'cups_read_client_conf()' - Read a client.conf file. |
1211 | | */ |
1212 | | |
1213 | | static void |
1214 | | cups_read_client_conf( |
1215 | | cups_file_t *fp, /* I - File to read */ |
1216 | | _cups_client_conf_t *cc) /* I - client.conf values */ |
1217 | 0 | { |
1218 | 0 | int linenum; /* Current line number */ |
1219 | 0 | char line[1024], /* Line from file */ |
1220 | 0 | *value; /* Pointer into line */ |
1221 | | |
1222 | | |
1223 | | /* |
1224 | | * Read from the file... |
1225 | | */ |
1226 | |
|
1227 | 0 | linenum = 0; |
1228 | 0 | while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) |
1229 | 0 | { |
1230 | 0 | if (!_cups_strcasecmp(line, "Encryption") && value) |
1231 | 0 | cups_set_encryption(cc, value); |
1232 | 0 | #ifndef __APPLE__ |
1233 | | /* |
1234 | | * The ServerName directive is not supported on macOS due to app |
1235 | | * sandboxing restrictions, i.e. not all apps request network access. |
1236 | | */ |
1237 | 0 | else if (!_cups_strcasecmp(line, "ServerName") && value) |
1238 | 0 | cups_set_server_name(cc, value); |
1239 | 0 | #endif /* !__APPLE__ */ |
1240 | 0 | else if (!_cups_strcasecmp(line, "User") && value) |
1241 | 0 | cups_set_user(cc, value); |
1242 | 0 | else if (!_cups_strcasecmp(line, "TrustOnFirstUse") && value) |
1243 | 0 | cc->trust_first = cups_boolean_value(value); |
1244 | 0 | else if (!_cups_strcasecmp(line, "AllowAnyRoot") && value) |
1245 | 0 | cc->any_root = cups_boolean_value(value); |
1246 | 0 | else if (!_cups_strcasecmp(line, "AllowExpiredCerts") && |
1247 | 0 | value) |
1248 | 0 | cc->expired_certs = cups_boolean_value(value); |
1249 | 0 | else if (!_cups_strcasecmp(line, "ValidateCerts") && value) |
1250 | 0 | cc->validate_certs = cups_boolean_value(value); |
1251 | | #ifdef HAVE_GSSAPI |
1252 | | else if (!_cups_strcasecmp(line, "GSSServiceName") && value) |
1253 | | cups_set_gss_service_name(cc, value); |
1254 | | #endif /* HAVE_GSSAPI */ |
1255 | | #ifdef HAVE_SSL |
1256 | | else if (!_cups_strcasecmp(line, "SSLOptions") && value) |
1257 | | cups_set_ssl_options(cc, value); |
1258 | | #endif /* HAVE_SSL */ |
1259 | 0 | } |
1260 | 0 | } |
1261 | | |
1262 | | |
1263 | | /* |
1264 | | * 'cups_set_default_ipp_port()' - Set the default IPP port value. |
1265 | | */ |
1266 | | |
1267 | | static void |
1268 | | cups_set_default_ipp_port( |
1269 | | _cups_globals_t *cg) /* I - Global data */ |
1270 | 0 | { |
1271 | 0 | const char *ipp_port; /* IPP_PORT environment variable */ |
1272 | | |
1273 | |
|
1274 | 0 | if ((ipp_port = getenv("IPP_PORT")) != NULL) |
1275 | 0 | { |
1276 | 0 | if ((cg->ipp_port = atoi(ipp_port)) <= 0) |
1277 | 0 | cg->ipp_port = CUPS_DEFAULT_IPP_PORT; |
1278 | 0 | } |
1279 | 0 | else |
1280 | 0 | cg->ipp_port = CUPS_DEFAULT_IPP_PORT; |
1281 | 0 | } |
1282 | | |
1283 | | /* |
1284 | | * 'cups_set_encryption()' - Set the Encryption value. |
1285 | | */ |
1286 | | |
1287 | | static void |
1288 | | cups_set_encryption( |
1289 | | _cups_client_conf_t *cc, /* I - client.conf values */ |
1290 | | const char *value) /* I - Value */ |
1291 | 0 | { |
1292 | 0 | if (!_cups_strcasecmp(value, "never")) |
1293 | 0 | cc->encryption = HTTP_ENCRYPTION_NEVER; |
1294 | 0 | else if (!_cups_strcasecmp(value, "always")) |
1295 | 0 | cc->encryption = HTTP_ENCRYPTION_ALWAYS; |
1296 | 0 | else if (!_cups_strcasecmp(value, "required")) |
1297 | 0 | cc->encryption = HTTP_ENCRYPTION_REQUIRED; |
1298 | 0 | else |
1299 | 0 | cc->encryption = HTTP_ENCRYPTION_IF_REQUESTED; |
1300 | 0 | } |
1301 | | |
1302 | | |
1303 | | /* |
1304 | | * 'cups_set_gss_service_name()' - Set the GSSServiceName value. |
1305 | | */ |
1306 | | |
1307 | | #ifdef HAVE_GSSAPI |
1308 | | static void |
1309 | | cups_set_gss_service_name( |
1310 | | _cups_client_conf_t *cc, /* I - client.conf values */ |
1311 | | const char *value) /* I - Value */ |
1312 | | { |
1313 | | strlcpy(cc->gss_service_name, value, sizeof(cc->gss_service_name)); |
1314 | | } |
1315 | | #endif /* HAVE_GSSAPI */ |
1316 | | |
1317 | | |
1318 | | /* |
1319 | | * 'cups_set_server_name()' - Set the ServerName value. |
1320 | | */ |
1321 | | |
1322 | | static void |
1323 | | cups_set_server_name( |
1324 | | _cups_client_conf_t *cc, /* I - client.conf values */ |
1325 | | const char *value) /* I - Value */ |
1326 | 0 | { |
1327 | 0 | strlcpy(cc->server_name, value, sizeof(cc->server_name)); |
1328 | 0 | } |
1329 | | |
1330 | | |
1331 | | /* |
1332 | | * 'cups_set_ssl_options()' - Set the SSLOptions value. |
1333 | | */ |
1334 | | |
1335 | | #ifdef HAVE_SSL |
1336 | | static void |
1337 | | cups_set_ssl_options( |
1338 | | _cups_client_conf_t *cc, /* I - client.conf values */ |
1339 | | const char *value) /* I - Value */ |
1340 | | { |
1341 | | /* |
1342 | | * SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyTLS1.0] [None] |
1343 | | */ |
1344 | | |
1345 | | int options = _HTTP_TLS_NONE, /* SSL/TLS options */ |
1346 | | min_version = _HTTP_TLS_1_0, /* Minimum SSL/TLS version */ |
1347 | | max_version = _HTTP_TLS_MAX; /* Maximum SSL/TLS version */ |
1348 | | char temp[256], /* Copy of value */ |
1349 | | *start, /* Start of option */ |
1350 | | *end; /* End of option */ |
1351 | | |
1352 | | |
1353 | | strlcpy(temp, value, sizeof(temp)); |
1354 | | |
1355 | | for (start = temp; *start; start = end) |
1356 | | { |
1357 | | /* |
1358 | | * Find end of keyword... |
1359 | | */ |
1360 | | |
1361 | | end = start; |
1362 | | while (*end && !_cups_isspace(*end)) |
1363 | | end ++; |
1364 | | |
1365 | | if (*end) |
1366 | | *end++ = '\0'; |
1367 | | |
1368 | | /* |
1369 | | * Compare... |
1370 | | */ |
1371 | | |
1372 | | if (!_cups_strcasecmp(start, "AllowRC4")) |
1373 | | options |= _HTTP_TLS_ALLOW_RC4; |
1374 | | else if (!_cups_strcasecmp(start, "AllowSSL3")) |
1375 | | min_version = _HTTP_TLS_SSL3; |
1376 | | else if (!_cups_strcasecmp(start, "AllowDH")) |
1377 | | options |= _HTTP_TLS_ALLOW_DH; |
1378 | | else if (!_cups_strcasecmp(start, "DenyCBC")) |
1379 | | options |= _HTTP_TLS_DENY_CBC; |
1380 | | else if (!_cups_strcasecmp(start, "DenyTLS1.0")) |
1381 | | min_version = _HTTP_TLS_1_1; |
1382 | | else if (!_cups_strcasecmp(start, "MaxTLS1.0")) |
1383 | | max_version = _HTTP_TLS_1_0; |
1384 | | else if (!_cups_strcasecmp(start, "MaxTLS1.1")) |
1385 | | max_version = _HTTP_TLS_1_1; |
1386 | | else if (!_cups_strcasecmp(start, "MaxTLS1.2")) |
1387 | | max_version = _HTTP_TLS_1_2; |
1388 | | else if (!_cups_strcasecmp(start, "MaxTLS1.3")) |
1389 | | max_version = _HTTP_TLS_1_3; |
1390 | | else if (!_cups_strcasecmp(start, "MinTLS1.0")) |
1391 | | min_version = _HTTP_TLS_1_0; |
1392 | | else if (!_cups_strcasecmp(start, "MinTLS1.1")) |
1393 | | min_version = _HTTP_TLS_1_1; |
1394 | | else if (!_cups_strcasecmp(start, "MinTLS1.2")) |
1395 | | min_version = _HTTP_TLS_1_2; |
1396 | | else if (!_cups_strcasecmp(start, "MinTLS1.3")) |
1397 | | min_version = _HTTP_TLS_1_3; |
1398 | | else if (!_cups_strcasecmp(start, "None")) |
1399 | | options = _HTTP_TLS_NONE; |
1400 | | } |
1401 | | |
1402 | | cc->ssl_options = options; |
1403 | | cc->ssl_max_version = max_version; |
1404 | | cc->ssl_min_version = min_version; |
1405 | | |
1406 | | DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x, min_version=%d, max_version=%d", (void *)cc, value, options, min_version, max_version)); |
1407 | | } |
1408 | | #endif /* HAVE_SSL */ |
1409 | | |
1410 | | |
1411 | | /* |
1412 | | * 'cups_set_user()' - Set the User value. |
1413 | | */ |
1414 | | |
1415 | | static void |
1416 | | cups_set_user( |
1417 | | _cups_client_conf_t *cc, /* I - client.conf values */ |
1418 | | const char *value) /* I - Value */ |
1419 | 0 | { |
1420 | 0 | strlcpy(cc->user, value, sizeof(cc->user)); |
1421 | 0 | } |