2 * Administration utility API definitions for CUPS.
4 * Copyright © 2007-2018 by Apple Inc.
5 * Copyright © 2001-2007 by Easy Software Products.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
12 * Include necessary headers...
15 #include "cups-private.h"
16 #include "debug-internal.h"
18 #include "adminutil.h"
23 # include <sys/wait.h>
31 static http_status_t
get_cupsd_conf(http_t
*http
, _cups_globals_t
*cg
,
32 time_t last_update
, char *name
,
33 size_t namelen
, int *remote
);
34 static void invalidate_cupsd_cache(_cups_globals_t
*cg
);
38 * 'cupsAdminCreateWindowsPPD()' - Create the Windows PPD file for a printer.
43 char * /* O - PPD file or NULL */
44 cupsAdminCreateWindowsPPD(
45 http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
46 const char *dest
, /* I - Printer or class */
47 char *buffer
, /* I - Filename buffer */
48 int bufsize
) /* I - Size of filename buffer */
58 * 'cupsAdminExportSamba()' - Export a printer to Samba.
63 int /* O - 1 on success, 0 on failure */
65 const char *dest
, /* I - Destination to export */
66 const char *ppd
, /* I - PPD file */
67 const char *samba_server
, /* I - Samba server */
68 const char *samba_user
, /* I - Samba username */
69 const char *samba_password
, /* I - Samba password */
70 FILE *logfile
) /* I - Log file, if any */
77 * 'cupsAdminGetServerSettings()' - Get settings from the server.
79 * The returned settings should be freed with cupsFreeOptions() when
80 * you are done with them.
82 * @since CUPS 1.3/macOS 10.5@
85 int /* O - 1 on success, 0 on failure */
86 cupsAdminGetServerSettings(
87 http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
88 int *num_settings
, /* O - Number of settings */
89 cups_option_t
**settings
) /* O - Settings */
91 int i
; /* Looping var */
92 cups_file_t
*cupsd
; /* cupsd.conf file */
93 char cupsdconf
[1024]; /* cupsd.conf filename */
94 int remote
; /* Remote cupsd.conf file? */
95 http_status_t status
; /* Status of getting cupsd.conf */
96 char line
[1024], /* Line from cupsd.conf file */
97 *value
; /* Value on line */
98 cups_option_t
*setting
; /* Current setting */
99 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
103 * Range check input...
109 * See if we are connected to the same server...
115 * Compare the connection hostname, port, and encryption settings to
116 * the cached defaults; these were initialized the first time we
120 if (strcmp(cg
->http
->hostname
, cg
->server
) ||
121 cg
->ipp_port
!= httpAddrPort(cg
->http
->hostaddr
) ||
122 (cg
->http
->encryption
!= cg
->encryption
&&
123 cg
->http
->encryption
== HTTP_ENCRYPTION_NEVER
))
126 * Need to close the current connection because something has changed...
135 * (Re)connect as needed...
140 if ((cg
->http
= httpConnect2(cupsServer(), ippPort(), NULL
, AF_UNSPEC
,
141 cupsEncryption(), 1, 0, NULL
)) == NULL
)
144 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE
, NULL
, 0);
146 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE
,
147 _("Unable to connect to host."), 1);
162 if (!http
|| !num_settings
|| !settings
)
164 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
179 * Get the cupsd.conf file...
182 if ((status
= get_cupsd_conf(http
, cg
, cg
->cupsd_update
, cupsdconf
,
183 sizeof(cupsdconf
), &remote
)) == HTTP_STATUS_OK
)
185 if ((cupsd
= cupsFileOpen(cupsdconf
, "r")) == NULL
)
187 char message
[1024]; /* Message string */
190 snprintf(message
, sizeof(message
),
191 _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")),
192 cupsdconf
, strerror(errno
));
193 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, message
, 0);
202 * Read the file, keeping track of what settings are enabled...
205 int remote_access
= 0, /* Remote access allowed? */
206 remote_admin
= 0, /* Remote administration allowed? */
207 remote_any
= 0, /* Remote access from anywhere allowed? */
208 browsing
= 1, /* Browsing enabled? */
209 cancel_policy
= 1, /* Cancel-job policy set? */
210 debug_logging
= 0; /* LogLevel debug set? */
211 int linenum
= 0, /* Line number in file */
212 in_location
= 0, /* In a location section? */
213 in_policy
= 0, /* In a policy section? */
214 in_cancel_job
= 0, /* In a cancel-job section? */
215 in_admin_location
= 0; /* In the /admin location? */
218 invalidate_cupsd_cache(cg
);
220 cg
->cupsd_update
= time(NULL
);
221 httpGetHostname(http
, cg
->cupsd_hostname
, sizeof(cg
->cupsd_hostname
));
223 while (cupsFileGetConf(cupsd
, line
, sizeof(line
), &value
, &linenum
))
225 if (!value
&& strncmp(line
, "</", 2))
226 value
= line
+ strlen(line
);
228 if ((!_cups_strcasecmp(line
, "Port") || !_cups_strcasecmp(line
, "Listen")) && value
)
230 char *port
; /* Pointer to port number, if any */
233 if ((port
= strrchr(value
, ':')) != NULL
)
235 else if (isdigit(*value
& 255))
238 * Listen on a port number implies remote access...
245 if (_cups_strcasecmp(value
, "localhost") && strcmp(value
, "127.0.0.1")
248 #endif /* AF_LOCAL */
250 && strcmp(value
, "[::1]")
251 #endif /* AF_INET6 */
255 else if (!_cups_strcasecmp(line
, "Browsing"))
257 browsing
= !_cups_strcasecmp(value
, "yes") ||
258 !_cups_strcasecmp(value
, "on") ||
259 !_cups_strcasecmp(value
, "true");
261 else if (!_cups_strcasecmp(line
, "LogLevel"))
263 debug_logging
= !_cups_strncasecmp(value
, "debug", 5);
265 else if (!_cups_strcasecmp(line
, "<Policy") &&
266 !_cups_strcasecmp(value
, "default"))
270 else if (!_cups_strcasecmp(line
, "</Policy>"))
274 else if (!_cups_strcasecmp(line
, "<Limit") && in_policy
&& value
)
277 * See if the policy limit is for the Cancel-Job operation...
280 char *valptr
; /* Pointer into value */
285 for (valptr
= value
; *valptr
&& !_cups_isspace(*valptr
); valptr
++);
290 if (!_cups_strcasecmp(value
, "cancel-job") ||
291 !_cups_strcasecmp(value
, "all"))
297 for (value
= valptr
; _cups_isspace(*value
); value
++);
300 else if (!_cups_strcasecmp(line
, "</Limit>"))
304 else if (!_cups_strcasecmp(line
, "Require") && in_cancel_job
)
308 else if (!_cups_strcasecmp(line
, "<Location") && value
)
310 in_admin_location
= !_cups_strcasecmp(value
, "/admin");
313 else if (!_cups_strcasecmp(line
, "</Location>"))
315 in_admin_location
= 0;
318 else if (!_cups_strcasecmp(line
, "Allow") && value
&&
319 _cups_strcasecmp(value
, "localhost") &&
320 _cups_strcasecmp(value
, "127.0.0.1")
323 #endif /* AF_LOCAL */
325 && strcmp(value
, "::1")
326 #endif /* AF_INET6 */
329 if (in_admin_location
)
331 else if (!_cups_strcasecmp(value
, "all"))
334 else if (line
[0] != '<' && !in_location
&& !in_policy
&&
335 _cups_strcasecmp(line
, "Allow") &&
336 _cups_strcasecmp(line
, "AuthType") &&
337 _cups_strcasecmp(line
, "Deny") &&
338 _cups_strcasecmp(line
, "Order") &&
339 _cups_strcasecmp(line
, "Require") &&
340 _cups_strcasecmp(line
, "Satisfy"))
341 cg
->cupsd_num_settings
= cupsAddOption(line
, value
,
342 cg
->cupsd_num_settings
,
343 &(cg
->cupsd_settings
));
346 cupsFileClose(cupsd
);
348 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_DEBUG_LOGGING
,
349 debug_logging
? "1" : "0",
350 cg
->cupsd_num_settings
,
351 &(cg
->cupsd_settings
));
353 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ADMIN
,
354 (remote_access
&& remote_admin
) ?
356 cg
->cupsd_num_settings
,
357 &(cg
->cupsd_settings
));
359 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ANY
,
360 remote_any
? "1" : "0",
361 cg
->cupsd_num_settings
,
362 &(cg
->cupsd_settings
));
364 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_SHARE_PRINTERS
,
365 (remote_access
&& browsing
) ? "1" :
367 cg
->cupsd_num_settings
,
368 &(cg
->cupsd_settings
));
370 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY
,
371 cancel_policy
? "1" : "0",
372 cg
->cupsd_num_settings
,
373 &(cg
->cupsd_settings
));
375 else if (status
!= HTTP_STATUS_NOT_MODIFIED
)
376 invalidate_cupsd_cache(cg
);
379 * Remove any temporary files and copy the settings array...
385 for (i
= cg
->cupsd_num_settings
, setting
= cg
->cupsd_settings
;
388 *num_settings
= cupsAddOption(setting
->name
, setting
->value
,
389 *num_settings
, settings
);
391 return (cg
->cupsd_num_settings
> 0);
396 * 'cupsAdminSetServerSettings()' - Set settings on the server.
398 * @since CUPS 1.3/macOS 10.5@
401 int /* O - 1 on success, 0 on failure */
402 cupsAdminSetServerSettings(
403 http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
404 int num_settings
, /* I - Number of settings */
405 cups_option_t
*settings
) /* I - Settings */
407 int i
; /* Looping var */
408 http_status_t status
; /* GET/PUT status */
409 const char *server_port_env
; /* SERVER_PORT env var */
410 int server_port
; /* IPP port for server */
411 cups_file_t
*cupsd
; /* cupsd.conf file */
412 char cupsdconf
[1024]; /* cupsd.conf filename */
413 int remote
; /* Remote cupsd.conf file? */
414 char tempfile
[1024]; /* Temporary new cupsd.conf */
415 cups_file_t
*temp
; /* Temporary file */
416 char line
[1024], /* Line from cupsd.conf file */
417 *value
; /* Value on line */
418 int linenum
, /* Line number in file */
419 in_location
, /* In a location section? */
420 in_policy
, /* In a policy section? */
421 in_default_policy
, /* In the default policy section? */
422 in_cancel_job
, /* In a cancel-job section? */
423 in_admin_location
, /* In the /admin location? */
424 in_conf_location
, /* In the /admin/conf location? */
425 in_log_location
, /* In the /admin/log location? */
426 in_root_location
; /* In the / location? */
427 const char *val
; /* Setting value */
428 int share_printers
, /* Share local printers */
429 remote_admin
, /* Remote administration allowed? */
430 remote_any
, /* Remote access from anywhere? */
431 user_cancel_any
, /* Cancel-job policy set? */
432 debug_logging
; /* LogLevel debug set? */
433 int wrote_port_listen
, /* Wrote the port/listen lines? */
434 wrote_browsing
, /* Wrote the browsing lines? */
435 wrote_policy
, /* Wrote the policy? */
436 wrote_loglevel
, /* Wrote the LogLevel line? */
437 wrote_admin_location
, /* Wrote the /admin location? */
438 wrote_conf_location
, /* Wrote the /admin/conf location? */
439 wrote_log_location
, /* Wrote the /admin/log location? */
440 wrote_root_location
; /* Wrote the / location? */
441 int indent
; /* Indentation */
442 int cupsd_num_settings
; /* New number of settings */
443 int old_share_printers
, /* Share local printers */
444 old_remote_admin
, /* Remote administration allowed? */
445 old_remote_any
, /* Remote access from anywhere? */
446 old_user_cancel_any
, /* Cancel-job policy set? */
447 old_debug_logging
; /* LogLevel debug set? */
448 cups_option_t
*cupsd_settings
, /* New settings */
449 *setting
; /* Current setting */
450 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
454 * Range check input...
458 http
= _cupsConnect();
460 if (!http
|| !num_settings
|| !settings
)
462 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
468 * Get the cupsd.conf file...
471 if (get_cupsd_conf(http
, cg
, 0, cupsdconf
, sizeof(cupsdconf
),
472 &remote
) == HTTP_STATUS_OK
)
474 if ((cupsd
= cupsFileOpen(cupsdconf
, "r")) == NULL
)
476 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, NULL
, 0);
484 * Get current settings...
487 if (!cupsAdminGetServerSettings(http
, &cupsd_num_settings
,
491 if ((val
= cupsGetOption(CUPS_SERVER_DEBUG_LOGGING
, cupsd_num_settings
,
492 cupsd_settings
)) != NULL
)
493 old_debug_logging
= atoi(val
);
495 old_debug_logging
= 0;
497 DEBUG_printf(("1cupsAdminSetServerSettings: old debug_logging=%d",
500 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ADMIN
, cupsd_num_settings
,
501 cupsd_settings
)) != NULL
)
502 old_remote_admin
= atoi(val
);
504 old_remote_admin
= 0;
506 DEBUG_printf(("1cupsAdminSetServerSettings: old remote_admin=%d",
509 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ANY
, cupsd_num_settings
,
510 cupsd_settings
)) != NULL
)
511 old_remote_any
= atoi(val
);
515 DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d",
518 if ((val
= cupsGetOption(CUPS_SERVER_SHARE_PRINTERS
, cupsd_num_settings
,
519 cupsd_settings
)) != NULL
)
520 old_share_printers
= atoi(val
);
522 old_share_printers
= 0;
524 DEBUG_printf(("1cupsAdminSetServerSettings: old share_printers=%d",
525 old_share_printers
));
527 if ((val
= cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY
, cupsd_num_settings
,
528 cupsd_settings
)) != NULL
)
529 old_user_cancel_any
= atoi(val
);
531 old_user_cancel_any
= 0;
533 DEBUG_printf(("1cupsAdminSetServerSettings: old user_cancel_any=%d",
534 old_user_cancel_any
));
536 cupsFreeOptions(cupsd_num_settings
, cupsd_settings
);
539 * Get basic settings...
542 if ((val
= cupsGetOption(CUPS_SERVER_DEBUG_LOGGING
, num_settings
,
545 debug_logging
= atoi(val
);
547 if (debug_logging
== old_debug_logging
)
550 * No change to this setting...
559 DEBUG_printf(("1cupsAdminSetServerSettings: debug_logging=%d",
562 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ANY
, num_settings
, settings
)) != NULL
)
564 remote_any
= atoi(val
);
566 if (remote_any
== old_remote_any
)
569 * No change to this setting...
578 DEBUG_printf(("1cupsAdminSetServerSettings: remote_any=%d", remote_any
));
580 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ADMIN
, num_settings
,
583 remote_admin
= atoi(val
);
585 if (remote_admin
== old_remote_admin
)
588 * No change to this setting...
597 DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d",
600 if ((val
= cupsGetOption(CUPS_SERVER_SHARE_PRINTERS
, num_settings
,
603 share_printers
= atoi(val
);
605 if (share_printers
== old_share_printers
)
608 * No change to this setting...
617 DEBUG_printf(("1cupsAdminSetServerSettings: share_printers=%d",
620 if ((val
= cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY
, num_settings
,
623 user_cancel_any
= atoi(val
);
625 if (user_cancel_any
== old_user_cancel_any
)
628 * No change to this setting...
631 user_cancel_any
= -1;
635 user_cancel_any
= -1;
637 DEBUG_printf(("1cupsAdminSetServerSettings: user_cancel_any=%d",
641 * Create a temporary file for the new cupsd.conf file...
644 if ((temp
= cupsTempFile2(tempfile
, sizeof(tempfile
))) == NULL
)
646 cupsFileClose(cupsd
);
651 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, NULL
, 0);
656 * Copy the old file to the new, making changes along the way...
659 cupsd_num_settings
= 0;
660 in_admin_location
= 0;
662 in_conf_location
= 0;
663 in_default_policy
= 0;
667 in_root_location
= 0;
669 wrote_admin_location
= 0;
671 wrote_conf_location
= 0;
672 wrote_log_location
= 0;
675 wrote_port_listen
= 0;
676 wrote_root_location
= 0;
679 if ((server_port_env
= getenv("SERVER_PORT")) != NULL
)
681 if ((server_port
= atoi(server_port_env
)) <= 0)
682 server_port
= ippPort();
685 server_port
= ippPort();
687 if (server_port
<= 0)
688 server_port
= IPP_PORT
;
690 while (cupsFileGetConf(cupsd
, line
, sizeof(line
), &value
, &linenum
))
692 if ((!_cups_strcasecmp(line
, "Port") || !_cups_strcasecmp(line
, "Listen")) &&
693 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
695 if (!wrote_port_listen
)
697 wrote_port_listen
= 1;
699 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
701 cupsFilePuts(temp
, "# Allow remote access\n");
702 cupsFilePrintf(temp
, "Port %d\n", server_port
);
706 cupsFilePuts(temp
, "# Only listen for connections from the local "
708 cupsFilePrintf(temp
, "Listen localhost:%d\n", server_port
);
711 #ifdef CUPS_DEFAULT_DOMAINSOCKET
712 if ((!value
|| strcmp(CUPS_DEFAULT_DOMAINSOCKET
, value
)) &&
713 !access(CUPS_DEFAULT_DOMAINSOCKET
, 0))
714 cupsFilePuts(temp
, "Listen " CUPS_DEFAULT_DOMAINSOCKET
"\n");
715 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
717 else if (value
&& value
[0] == '/'
718 #ifdef CUPS_DEFAULT_DOMAINSOCKET
719 && strcmp(CUPS_DEFAULT_DOMAINSOCKET
, value
)
720 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
722 cupsFilePrintf(temp
, "Listen %s\n", value
);
724 else if ((!_cups_strcasecmp(line
, "Browsing") ||
725 !_cups_strcasecmp(line
, "BrowseLocalProtocols")) &&
730 int new_share_printers
= (share_printers
> 0 ||
731 (share_printers
== -1 &&
732 old_share_printers
> 0));
736 if (new_share_printers
)
738 const char *localp
= cupsGetOption("BrowseLocalProtocols",
739 num_settings
, settings
);
741 if (!localp
|| !localp
[0])
742 localp
= cupsGetOption("BrowseLocalProtocols", cupsd_num_settings
,
745 cupsFilePuts(temp
, "# Share local printers on the local network.\n");
746 cupsFilePuts(temp
, "Browsing On\n");
749 localp
= CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS
;
751 cupsFilePrintf(temp
, "BrowseLocalProtocols %s\n", localp
);
753 cupsd_num_settings
= cupsAddOption("BrowseLocalProtocols", localp
,
759 cupsFilePuts(temp
, "# Disable printer sharing.\n");
760 cupsFilePuts(temp
, "Browsing Off\n");
764 else if (!_cups_strcasecmp(line
, "LogLevel") && debug_logging
>= 0)
771 "# Show troubleshooting information in error_log.\n");
772 cupsFilePuts(temp
, "LogLevel debug\n");
776 cupsFilePuts(temp
, "# Show general information in error_log.\n");
777 cupsFilePuts(temp
, "LogLevel " CUPS_DEFAULT_LOG_LEVEL
"\n");
780 else if (!_cups_strcasecmp(line
, "<Policy"))
782 in_default_policy
= !_cups_strcasecmp(value
, "default");
785 cupsFilePrintf(temp
, "%s %s>\n", line
, value
);
788 else if (!_cups_strcasecmp(line
, "</Policy>"))
791 if (!wrote_policy
&& in_default_policy
)
795 if (!user_cancel_any
)
796 cupsFilePuts(temp
, " # Only the owner or an administrator can "
798 " <Limit Cancel-Job>\n"
799 " Order deny,allow\n"
800 " Require user @OWNER "
801 CUPS_DEFAULT_PRINTOPERATOR_AUTH
"\n"
806 in_default_policy
= 0;
808 cupsFilePuts(temp
, "</Policy>\n");
810 else if (!_cups_strcasecmp(line
, "<Location"))
814 if (!strcmp(value
, "/admin"))
815 in_admin_location
= 1;
816 else if (!strcmp(value
, "/admin/conf"))
817 in_conf_location
= 1;
818 else if (!strcmp(value
, "/admin/log"))
820 else if (!strcmp(value
, "/"))
821 in_root_location
= 1;
823 cupsFilePrintf(temp
, "%s %s>\n", line
, value
);
825 else if (!_cups_strcasecmp(line
, "</Location>"))
829 if (in_admin_location
&& remote_admin
>= 0)
831 wrote_admin_location
= 1;
834 cupsFilePuts(temp
, " # Allow remote administration...\n");
835 else if (remote_admin
== 0)
836 cupsFilePuts(temp
, " # Restrict access to the admin pages...\n");
838 cupsFilePuts(temp
, " Order allow,deny\n");
841 cupsFilePrintf(temp
, " Allow %s\n",
842 remote_any
> 0 ? "all" : "@LOCAL");
844 else if (in_conf_location
&& remote_admin
>= 0)
846 wrote_conf_location
= 1;
849 cupsFilePuts(temp
, " # Allow remote access to the configuration "
852 cupsFilePuts(temp
, " # Restrict access to the configuration "
855 cupsFilePuts(temp
, " Order allow,deny\n");
858 cupsFilePrintf(temp
, " Allow %s\n",
859 remote_any
> 0 ? "all" : "@LOCAL");
861 else if (in_log_location
&& remote_admin
>= 0)
863 wrote_log_location
= 1;
866 cupsFilePuts(temp
, " # Allow remote access to the log "
869 cupsFilePuts(temp
, " # Restrict access to the log "
872 cupsFilePuts(temp
, " Order allow,deny\n");
875 cupsFilePrintf(temp
, " Allow %s\n",
876 remote_any
> 0 ? "all" : "@LOCAL");
878 else if (in_root_location
&&
879 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
881 wrote_root_location
= 1;
883 if (remote_admin
> 0 && share_printers
> 0)
884 cupsFilePuts(temp
, " # Allow shared printing and remote "
885 "administration...\n");
886 else if (remote_admin
> 0)
887 cupsFilePuts(temp
, " # Allow remote administration...\n");
888 else if (share_printers
> 0)
889 cupsFilePuts(temp
, " # Allow shared printing...\n");
890 else if (remote_any
> 0)
891 cupsFilePuts(temp
, " # Allow remote access...\n");
893 cupsFilePuts(temp
, " # Restrict access to the server...\n");
895 cupsFilePuts(temp
, " Order allow,deny\n");
897 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
898 cupsFilePrintf(temp
, " Allow %s\n",
899 remote_any
> 0 ? "all" : "@LOCAL");
902 in_admin_location
= 0;
903 in_conf_location
= 0;
905 in_root_location
= 0;
907 cupsFilePuts(temp
, "</Location>\n");
909 else if (!_cups_strcasecmp(line
, "<Limit"))
911 if (in_default_policy
)
914 * See if the policy limit is for the Cancel-Job operation...
917 char *valptr
; /* Pointer into value */
920 if (!_cups_strcasecmp(value
, "cancel-job") && user_cancel_any
>= 0)
923 * Don't write anything for this limit section...
930 cupsFilePrintf(temp
, "%*s%s", indent
, "", line
);
934 for (valptr
= value
; *valptr
&& !_cups_isspace(*valptr
); valptr
++);
939 if (!_cups_strcasecmp(value
, "cancel-job") && user_cancel_any
>= 0)
942 * Write everything except for this definition...
948 cupsFilePrintf(temp
, " %s", value
);
950 for (value
= valptr
; _cups_isspace(*value
); value
++);
953 cupsFilePuts(temp
, ">\n");
957 cupsFilePrintf(temp
, "%*s%s %s>\n", indent
, "", line
, value
);
961 else if (!_cups_strcasecmp(line
, "</Limit>") && in_cancel_job
)
965 if (in_cancel_job
== 1)
966 cupsFilePuts(temp
, " </Limit>\n");
970 if (!user_cancel_any
)
971 cupsFilePuts(temp
, " # Only the owner or an administrator can cancel "
973 " <Limit Cancel-Job>\n"
974 " Order deny,allow\n"
975 " Require user @OWNER "
976 CUPS_DEFAULT_PRINTOPERATOR_AUTH
"\n"
981 else if ((((in_admin_location
|| in_conf_location
|| in_root_location
) &&
982 (remote_admin
>= 0 || remote_any
>= 0)) ||
983 (in_root_location
&& share_printers
>= 0)) &&
984 (!_cups_strcasecmp(line
, "Allow") || !_cups_strcasecmp(line
, "Deny") ||
985 !_cups_strcasecmp(line
, "Order")))
987 else if (in_cancel_job
== 2)
989 else if (line
[0] == '<')
993 cupsFilePrintf(temp
, "%*s%s %s>\n", indent
, "", line
, value
);
1001 cupsFilePrintf(temp
, "%*s%s\n", indent
, "", line
);
1004 else if (!in_policy
&& !in_location
&&
1005 (val
= cupsGetOption(line
, num_settings
, settings
)) != NULL
)
1008 * Replace this directive's value with the new one...
1011 cupsd_num_settings
= cupsAddOption(line
, val
, cupsd_num_settings
,
1015 * Write the new value in its place, without indentation since we
1016 * only support setting root directives, not in sections...
1019 cupsFilePrintf(temp
, "%s %s\n", line
, val
);
1023 if (!in_policy
&& !in_location
)
1026 * Record the non-policy, non-location directives that we find
1027 * in the server settings, since we cache this info and record it
1028 * in cupsAdminGetServerSettings()...
1031 cupsd_num_settings
= cupsAddOption(line
, value
, cupsd_num_settings
,
1035 cupsFilePrintf(temp
, "%*s%s %s\n", indent
, "", line
, value
);
1038 cupsFilePrintf(temp
, "%*s%s\n", indent
, "", line
);
1042 * Write any missing info...
1045 if (!wrote_browsing
&& share_printers
>= 0)
1047 if (share_printers
> 0)
1049 cupsFilePuts(temp
, "# Share local printers on the local network.\n");
1050 cupsFilePuts(temp
, "Browsing On\n");
1054 cupsFilePuts(temp
, "# Disable printer sharing and shared printers.\n");
1055 cupsFilePuts(temp
, "Browsing Off\n");
1059 if (!wrote_loglevel
&& debug_logging
>= 0)
1063 cupsFilePuts(temp
, "# Show troubleshooting information in error_log.\n");
1064 cupsFilePuts(temp
, "LogLevel debug\n");
1068 cupsFilePuts(temp
, "# Show general information in error_log.\n");
1069 cupsFilePuts(temp
, "LogLevel " CUPS_DEFAULT_LOG_LEVEL
"\n");
1073 if (!wrote_port_listen
&&
1074 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
1076 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
1078 cupsFilePuts(temp
, "# Allow remote access\n");
1079 cupsFilePrintf(temp
, "Port %d\n", ippPort());
1084 "# Only listen for connections from the local machine.\n");
1085 cupsFilePrintf(temp
, "Listen localhost:%d\n", ippPort());
1088 #ifdef CUPS_DEFAULT_DOMAINSOCKET
1089 if (!access(CUPS_DEFAULT_DOMAINSOCKET
, 0))
1090 cupsFilePuts(temp
, "Listen " CUPS_DEFAULT_DOMAINSOCKET
"\n");
1091 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
1094 if (!wrote_root_location
&&
1095 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
1097 if (remote_admin
> 0 && share_printers
> 0)
1099 "# Allow shared printing and remote administration...\n");
1100 else if (remote_admin
> 0)
1101 cupsFilePuts(temp
, "# Allow remote administration...\n");
1102 else if (share_printers
> 0)
1103 cupsFilePuts(temp
, "# Allow shared printing...\n");
1104 else if (remote_any
> 0)
1105 cupsFilePuts(temp
, "# Allow remote access...\n");
1107 cupsFilePuts(temp
, "# Restrict access to the server...\n");
1109 cupsFilePuts(temp
, "<Location />\n"
1110 " Order allow,deny\n");
1112 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
1113 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1115 cupsFilePuts(temp
, "</Location>\n");
1118 if (!wrote_admin_location
&& remote_admin
>= 0)
1121 cupsFilePuts(temp
, "# Allow remote administration...\n");
1123 cupsFilePuts(temp
, "# Restrict access to the admin pages...\n");
1125 cupsFilePuts(temp
, "<Location /admin>\n"
1126 " Order allow,deny\n");
1129 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1131 cupsFilePuts(temp
, "</Location>\n");
1134 if (!wrote_conf_location
&& remote_admin
>= 0)
1138 "# Allow remote access to the configuration files...\n");
1140 cupsFilePuts(temp
, "# Restrict access to the configuration files...\n");
1142 cupsFilePuts(temp
, "<Location /admin/conf>\n"
1143 " AuthType Default\n"
1144 " Require user @SYSTEM\n"
1145 " Order allow,deny\n");
1148 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1150 cupsFilePuts(temp
, "</Location>\n");
1153 if (!wrote_log_location
&& remote_admin
>= 0)
1157 "# Allow remote access to the log files...\n");
1159 cupsFilePuts(temp
, "# Restrict access to the log files...\n");
1161 cupsFilePuts(temp
, "<Location /admin/log>\n"
1162 " AuthType Default\n"
1163 " Require user @SYSTEM\n"
1164 " Order allow,deny\n");
1167 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1169 cupsFilePuts(temp
, "</Location>\n");
1172 if (!wrote_policy
&& user_cancel_any
>= 0)
1174 cupsFilePuts(temp
, "<Policy default>\n"
1175 " # Job-related operations must be done by the owner "
1176 "or an administrator...\n"
1177 " <Limit Send-Document Send-URI Hold-Job Release-Job "
1178 "Restart-Job Purge-Jobs Set-Job-Attributes "
1179 "Create-Job-Subscription Renew-Subscription "
1180 "Cancel-Subscription Get-Notifications Reprocess-Job "
1181 "Cancel-Current-Job Suspend-Current-Job Resume-Job "
1183 " Require user @OWNER @SYSTEM\n"
1184 " Order deny,allow\n"
1186 " # All administration operations require an "
1187 "administrator to authenticate...\n"
1188 " <Limit Pause-Printer Resume-Printer "
1189 "Set-Printer-Attributes Enable-Printer "
1190 "Disable-Printer Pause-Printer-After-Current-Job "
1191 "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer "
1192 "Activate-Printer Restart-Printer Shutdown-Printer "
1193 "Startup-Printer Promote-Job Schedule-Job-After "
1194 "CUPS-Add-Printer CUPS-Delete-Printer "
1195 "CUPS-Add-Class CUPS-Delete-Class "
1196 "CUPS-Accept-Jobs CUPS-Reject-Jobs "
1197 "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n"
1198 " AuthType Default\n"
1199 " Require user @SYSTEM\n"
1200 " Order deny,allow\n"
1203 if (!user_cancel_any
)
1204 cupsFilePuts(temp
, " # Only the owner or an administrator can cancel "
1206 " <Limit Cancel-Job>\n"
1207 " Order deny,allow\n"
1208 " Require user @OWNER "
1209 CUPS_DEFAULT_PRINTOPERATOR_AUTH
"\n"
1212 cupsFilePuts(temp
, " <Limit All>\n"
1213 " Order deny,allow\n"
1218 for (i
= num_settings
, setting
= settings
; i
> 0; i
--, setting
++)
1219 if (setting
->name
[0] != '_' &&
1220 _cups_strcasecmp(setting
->name
, "Listen") &&
1221 _cups_strcasecmp(setting
->name
, "Port") &&
1222 !cupsGetOption(setting
->name
, cupsd_num_settings
, cupsd_settings
))
1225 * Add this directive to the list of directives we have written...
1228 cupsd_num_settings
= cupsAddOption(setting
->name
, setting
->value
,
1229 cupsd_num_settings
, &cupsd_settings
);
1232 * Write the new value, without indentation since we only support
1233 * setting root directives, not in sections...
1236 cupsFilePrintf(temp
, "%s %s\n", setting
->name
, setting
->value
);
1239 cupsFileClose(cupsd
);
1240 cupsFileClose(temp
);
1243 * Upload the configuration file to the server...
1246 status
= cupsPutFile(http
, "/admin/conf/cupsd.conf", tempfile
);
1248 if (status
== HTTP_STATUS_CREATED
)
1251 * Updated OK, add the basic settings...
1254 if (debug_logging
>= 0)
1255 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_DEBUG_LOGGING
,
1256 debug_logging
? "1" : "0",
1257 cupsd_num_settings
, &cupsd_settings
);
1259 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_DEBUG_LOGGING
,
1260 old_debug_logging
? "1" : "0",
1261 cupsd_num_settings
, &cupsd_settings
);
1263 if (remote_admin
>= 0)
1264 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ADMIN
,
1265 remote_admin
? "1" : "0",
1266 cupsd_num_settings
, &cupsd_settings
);
1268 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ADMIN
,
1269 old_remote_admin
? "1" : "0",
1270 cupsd_num_settings
, &cupsd_settings
);
1272 if (remote_any
>= 0)
1273 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ANY
,
1274 remote_any
? "1" : "0",
1275 cupsd_num_settings
, &cupsd_settings
);
1277 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ANY
,
1278 old_remote_any
? "1" : "0",
1279 cupsd_num_settings
, &cupsd_settings
);
1281 if (share_printers
>= 0)
1282 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_SHARE_PRINTERS
,
1283 share_printers
? "1" : "0",
1284 cupsd_num_settings
, &cupsd_settings
);
1286 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_SHARE_PRINTERS
,
1287 old_share_printers
? "1" : "0",
1288 cupsd_num_settings
, &cupsd_settings
);
1290 if (user_cancel_any
>= 0)
1291 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY
,
1292 user_cancel_any
? "1" : "0",
1293 cupsd_num_settings
, &cupsd_settings
);
1295 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY
,
1296 old_user_cancel_any
? "1" : "0",
1297 cupsd_num_settings
, &cupsd_settings
);
1300 * Save the new values...
1303 invalidate_cupsd_cache(cg
);
1305 cg
->cupsd_num_settings
= cupsd_num_settings
;
1306 cg
->cupsd_settings
= cupsd_settings
;
1307 cg
->cupsd_update
= time(NULL
);
1309 httpGetHostname(http
, cg
->cupsd_hostname
, sizeof(cg
->cupsd_hostname
));
1312 cupsFreeOptions(cupsd_num_settings
, cupsd_settings
);
1315 * Remote our temp files and return...
1323 return (status
== HTTP_STATUS_CREATED
);
1328 * 'get_cupsd_conf()' - Get the current cupsd.conf file.
1331 static http_status_t
/* O - Status of request */
1333 http_t
*http
, /* I - Connection to server */
1334 _cups_globals_t
*cg
, /* I - Global data */
1335 time_t last_update
, /* I - Last update time for file */
1336 char *name
, /* I - Filename buffer */
1337 size_t namesize
, /* I - Size of filename buffer */
1338 int *remote
) /* O - Remote file? */
1340 int fd
; /* Temporary file descriptor */
1342 struct stat info
; /* cupsd.conf file information */
1344 http_status_t status
; /* Status of getting cupsd.conf */
1345 char host
[HTTP_MAX_HOST
]; /* Hostname for connection */
1349 * See if we already have the data we need...
1352 httpGetHostname(http
, host
, sizeof(host
));
1354 if (_cups_strcasecmp(cg
->cupsd_hostname
, host
))
1355 invalidate_cupsd_cache(cg
);
1357 snprintf(name
, namesize
, "%s/cupsd.conf", cg
->cups_serverroot
);
1361 if (!_cups_strcasecmp(host
, "localhost") && !access(name
, R_OK
))
1364 * Read the local file rather than using HTTP...
1367 if (stat(name
, &info
))
1369 char message
[1024]; /* Message string */
1372 snprintf(message
, sizeof(message
),
1373 _cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")),
1374 name
, strerror(errno
));
1375 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, message
, 0);
1379 return (HTTP_STATUS_SERVER_ERROR
);
1381 else if (last_update
&& info
.st_mtime
<= last_update
)
1382 status
= HTTP_STATUS_NOT_MODIFIED
;
1384 status
= HTTP_STATUS_OK
;
1387 #endif /* !_WIN32 */
1390 * Read cupsd.conf via a HTTP GET request...
1393 if ((fd
= cupsTempFd(name
, (int)namesize
)) < 0)
1397 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, NULL
, 0);
1399 invalidate_cupsd_cache(cg
);
1401 return (HTTP_STATUS_SERVER_ERROR
);
1406 httpClearFields(http
);
1409 httpSetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
,
1410 httpGetDateString(last_update
));
1412 status
= cupsGetFd(http
, "/admin/conf/cupsd.conf", fd
);
1416 if (status
!= HTTP_STATUS_OK
)
1428 * 'invalidate_cupsd_cache()' - Invalidate the cached cupsd.conf settings.
1432 invalidate_cupsd_cache(
1433 _cups_globals_t
*cg
) /* I - Global data */
1435 cupsFreeOptions(cg
->cupsd_num_settings
, cg
->cupsd_settings
);
1437 cg
->cupsd_hostname
[0] = '\0';
1438 cg
->cupsd_update
= 0;
1439 cg
->cupsd_num_settings
= 0;
1440 cg
->cupsd_settings
= NULL
;