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 */
62 * 'cupsAdminExportSamba()' - Export a printer to Samba.
67 int /* O - 1 on success, 0 on failure */
69 const char *dest
, /* I - Destination to export */
70 const char *ppd
, /* I - PPD file */
71 const char *samba_server
, /* I - Samba server */
72 const char *samba_user
, /* I - Samba username */
73 const char *samba_password
, /* I - Samba password */
74 FILE *logfile
) /* I - Log file, if any */
88 * 'cupsAdminGetServerSettings()' - Get settings from the server.
90 * The returned settings should be freed with cupsFreeOptions() when
91 * you are done with them.
93 * @since CUPS 1.3/macOS 10.5@
96 int /* O - 1 on success, 0 on failure */
97 cupsAdminGetServerSettings(
98 http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
99 int *num_settings
, /* O - Number of settings */
100 cups_option_t
**settings
) /* O - Settings */
102 int i
; /* Looping var */
103 cups_file_t
*cupsd
; /* cupsd.conf file */
104 char cupsdconf
[1024]; /* cupsd.conf filename */
105 int remote
; /* Remote cupsd.conf file? */
106 http_status_t status
; /* Status of getting cupsd.conf */
107 char line
[1024], /* Line from cupsd.conf file */
108 *value
; /* Value on line */
109 cups_option_t
*setting
; /* Current setting */
110 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
114 * Range check input...
120 * See if we are connected to the same server...
126 * Compare the connection hostname, port, and encryption settings to
127 * the cached defaults; these were initialized the first time we
131 if (strcmp(cg
->http
->hostname
, cg
->server
) ||
132 cg
->ipp_port
!= httpAddrPort(cg
->http
->hostaddr
) ||
133 (cg
->http
->encryption
!= cg
->encryption
&&
134 cg
->http
->encryption
== HTTP_ENCRYPTION_NEVER
))
137 * Need to close the current connection because something has changed...
146 * (Re)connect as needed...
151 if ((cg
->http
= httpConnect2(cupsServer(), ippPort(), NULL
, AF_UNSPEC
,
152 cupsEncryption(), 1, 0, NULL
)) == NULL
)
155 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE
, NULL
, 0);
157 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE
,
158 _("Unable to connect to host."), 1);
173 if (!http
|| !num_settings
|| !settings
)
175 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
190 * Get the cupsd.conf file...
193 if ((status
= get_cupsd_conf(http
, cg
, cg
->cupsd_update
, cupsdconf
,
194 sizeof(cupsdconf
), &remote
)) == HTTP_STATUS_OK
)
196 if ((cupsd
= cupsFileOpen(cupsdconf
, "r")) == NULL
)
198 char message
[1024]; /* Message string */
201 snprintf(message
, sizeof(message
),
202 _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")),
203 cupsdconf
, strerror(errno
));
204 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, message
, 0);
213 * Read the file, keeping track of what settings are enabled...
216 int remote_access
= 0, /* Remote access allowed? */
217 remote_admin
= 0, /* Remote administration allowed? */
218 remote_any
= 0, /* Remote access from anywhere allowed? */
219 browsing
= 1, /* Browsing enabled? */
220 cancel_policy
= 1, /* Cancel-job policy set? */
221 debug_logging
= 0; /* LogLevel debug set? */
222 int linenum
= 0, /* Line number in file */
223 in_location
= 0, /* In a location section? */
224 in_policy
= 0, /* In a policy section? */
225 in_cancel_job
= 0, /* In a cancel-job section? */
226 in_admin_location
= 0; /* In the /admin location? */
229 invalidate_cupsd_cache(cg
);
231 cg
->cupsd_update
= time(NULL
);
232 httpGetHostname(http
, cg
->cupsd_hostname
, sizeof(cg
->cupsd_hostname
));
234 while (cupsFileGetConf(cupsd
, line
, sizeof(line
), &value
, &linenum
))
236 if (!value
&& strncmp(line
, "</", 2))
237 value
= line
+ strlen(line
);
239 if ((!_cups_strcasecmp(line
, "Port") || !_cups_strcasecmp(line
, "Listen")) && value
)
241 char *port
; /* Pointer to port number, if any */
244 if ((port
= strrchr(value
, ':')) != NULL
)
246 else if (isdigit(*value
& 255))
249 * Listen on a port number implies remote access...
256 if (_cups_strcasecmp(value
, "localhost") && strcmp(value
, "127.0.0.1")
259 #endif /* AF_LOCAL */
261 && strcmp(value
, "[::1]")
262 #endif /* AF_INET6 */
266 else if (!_cups_strcasecmp(line
, "Browsing"))
268 browsing
= !_cups_strcasecmp(value
, "yes") ||
269 !_cups_strcasecmp(value
, "on") ||
270 !_cups_strcasecmp(value
, "true");
272 else if (!_cups_strcasecmp(line
, "LogLevel"))
274 debug_logging
= !_cups_strncasecmp(value
, "debug", 5);
276 else if (!_cups_strcasecmp(line
, "<Policy") &&
277 !_cups_strcasecmp(value
, "default"))
281 else if (!_cups_strcasecmp(line
, "</Policy>"))
285 else if (!_cups_strcasecmp(line
, "<Limit") && in_policy
&& value
)
288 * See if the policy limit is for the Cancel-Job operation...
291 char *valptr
; /* Pointer into value */
296 for (valptr
= value
; *valptr
&& !_cups_isspace(*valptr
); valptr
++);
301 if (!_cups_strcasecmp(value
, "cancel-job") ||
302 !_cups_strcasecmp(value
, "all"))
308 for (value
= valptr
; _cups_isspace(*value
); value
++);
311 else if (!_cups_strcasecmp(line
, "</Limit>"))
315 else if (!_cups_strcasecmp(line
, "Require") && in_cancel_job
)
319 else if (!_cups_strcasecmp(line
, "<Location") && value
)
321 in_admin_location
= !_cups_strcasecmp(value
, "/admin");
324 else if (!_cups_strcasecmp(line
, "</Location>"))
326 in_admin_location
= 0;
329 else if (!_cups_strcasecmp(line
, "Allow") && value
&&
330 _cups_strcasecmp(value
, "localhost") &&
331 _cups_strcasecmp(value
, "127.0.0.1")
334 #endif /* AF_LOCAL */
336 && strcmp(value
, "::1")
337 #endif /* AF_INET6 */
340 if (in_admin_location
)
342 else if (!_cups_strcasecmp(value
, "all"))
345 else if (line
[0] != '<' && !in_location
&& !in_policy
&&
346 _cups_strcasecmp(line
, "Allow") &&
347 _cups_strcasecmp(line
, "AuthType") &&
348 _cups_strcasecmp(line
, "Deny") &&
349 _cups_strcasecmp(line
, "Order") &&
350 _cups_strcasecmp(line
, "Require") &&
351 _cups_strcasecmp(line
, "Satisfy"))
352 cg
->cupsd_num_settings
= cupsAddOption(line
, value
,
353 cg
->cupsd_num_settings
,
354 &(cg
->cupsd_settings
));
357 cupsFileClose(cupsd
);
359 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_DEBUG_LOGGING
,
360 debug_logging
? "1" : "0",
361 cg
->cupsd_num_settings
,
362 &(cg
->cupsd_settings
));
364 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ADMIN
,
365 (remote_access
&& remote_admin
) ?
367 cg
->cupsd_num_settings
,
368 &(cg
->cupsd_settings
));
370 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ANY
,
371 remote_any
? "1" : "0",
372 cg
->cupsd_num_settings
,
373 &(cg
->cupsd_settings
));
375 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_SHARE_PRINTERS
,
376 (remote_access
&& browsing
) ? "1" :
378 cg
->cupsd_num_settings
,
379 &(cg
->cupsd_settings
));
381 cg
->cupsd_num_settings
= cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY
,
382 cancel_policy
? "1" : "0",
383 cg
->cupsd_num_settings
,
384 &(cg
->cupsd_settings
));
386 else if (status
!= HTTP_STATUS_NOT_MODIFIED
)
387 invalidate_cupsd_cache(cg
);
390 * Remove any temporary files and copy the settings array...
396 for (i
= cg
->cupsd_num_settings
, setting
= cg
->cupsd_settings
;
399 *num_settings
= cupsAddOption(setting
->name
, setting
->value
,
400 *num_settings
, settings
);
402 return (cg
->cupsd_num_settings
> 0);
407 * 'cupsAdminSetServerSettings()' - Set settings on the server.
409 * @since CUPS 1.3/macOS 10.5@
412 int /* O - 1 on success, 0 on failure */
413 cupsAdminSetServerSettings(
414 http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
415 int num_settings
, /* I - Number of settings */
416 cups_option_t
*settings
) /* I - Settings */
418 int i
; /* Looping var */
419 http_status_t status
; /* GET/PUT status */
420 const char *server_port_env
; /* SERVER_PORT env var */
421 int server_port
; /* IPP port for server */
422 cups_file_t
*cupsd
; /* cupsd.conf file */
423 char cupsdconf
[1024]; /* cupsd.conf filename */
424 int remote
; /* Remote cupsd.conf file? */
425 char tempfile
[1024]; /* Temporary new cupsd.conf */
426 cups_file_t
*temp
; /* Temporary file */
427 char line
[1024], /* Line from cupsd.conf file */
428 *value
; /* Value on line */
429 int linenum
, /* Line number in file */
430 in_location
, /* In a location section? */
431 in_policy
, /* In a policy section? */
432 in_default_policy
, /* In the default policy section? */
433 in_cancel_job
, /* In a cancel-job section? */
434 in_admin_location
, /* In the /admin location? */
435 in_conf_location
, /* In the /admin/conf location? */
436 in_log_location
, /* In the /admin/log location? */
437 in_root_location
; /* In the / location? */
438 const char *val
; /* Setting value */
439 int share_printers
, /* Share local printers */
440 remote_admin
, /* Remote administration allowed? */
441 remote_any
, /* Remote access from anywhere? */
442 user_cancel_any
, /* Cancel-job policy set? */
443 debug_logging
; /* LogLevel debug set? */
444 int wrote_port_listen
, /* Wrote the port/listen lines? */
445 wrote_browsing
, /* Wrote the browsing lines? */
446 wrote_policy
, /* Wrote the policy? */
447 wrote_loglevel
, /* Wrote the LogLevel line? */
448 wrote_admin_location
, /* Wrote the /admin location? */
449 wrote_conf_location
, /* Wrote the /admin/conf location? */
450 wrote_log_location
, /* Wrote the /admin/log location? */
451 wrote_root_location
; /* Wrote the / location? */
452 int indent
; /* Indentation */
453 int cupsd_num_settings
; /* New number of settings */
454 int old_share_printers
, /* Share local printers */
455 old_remote_admin
, /* Remote administration allowed? */
456 old_remote_any
, /* Remote access from anywhere? */
457 old_user_cancel_any
, /* Cancel-job policy set? */
458 old_debug_logging
; /* LogLevel debug set? */
459 cups_option_t
*cupsd_settings
, /* New settings */
460 *setting
; /* Current setting */
461 _cups_globals_t
*cg
= _cupsGlobals(); /* Global data */
465 * Range check input...
469 http
= _cupsConnect();
471 if (!http
|| !num_settings
|| !settings
)
473 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, strerror(EINVAL
), 0);
479 * Get the cupsd.conf file...
482 if (get_cupsd_conf(http
, cg
, 0, cupsdconf
, sizeof(cupsdconf
),
483 &remote
) == HTTP_STATUS_OK
)
485 if ((cupsd
= cupsFileOpen(cupsdconf
, "r")) == NULL
)
487 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, NULL
, 0);
495 * Get current settings...
498 if (!cupsAdminGetServerSettings(http
, &cupsd_num_settings
,
502 if ((val
= cupsGetOption(CUPS_SERVER_DEBUG_LOGGING
, cupsd_num_settings
,
503 cupsd_settings
)) != NULL
)
504 old_debug_logging
= atoi(val
);
506 old_debug_logging
= 0;
508 DEBUG_printf(("1cupsAdminSetServerSettings: old debug_logging=%d",
511 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ADMIN
, cupsd_num_settings
,
512 cupsd_settings
)) != NULL
)
513 old_remote_admin
= atoi(val
);
515 old_remote_admin
= 0;
517 DEBUG_printf(("1cupsAdminSetServerSettings: old remote_admin=%d",
520 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ANY
, cupsd_num_settings
,
521 cupsd_settings
)) != NULL
)
522 old_remote_any
= atoi(val
);
526 DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d",
529 if ((val
= cupsGetOption(CUPS_SERVER_SHARE_PRINTERS
, cupsd_num_settings
,
530 cupsd_settings
)) != NULL
)
531 old_share_printers
= atoi(val
);
533 old_share_printers
= 0;
535 DEBUG_printf(("1cupsAdminSetServerSettings: old share_printers=%d",
536 old_share_printers
));
538 if ((val
= cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY
, cupsd_num_settings
,
539 cupsd_settings
)) != NULL
)
540 old_user_cancel_any
= atoi(val
);
542 old_user_cancel_any
= 0;
544 DEBUG_printf(("1cupsAdminSetServerSettings: old user_cancel_any=%d",
545 old_user_cancel_any
));
547 cupsFreeOptions(cupsd_num_settings
, cupsd_settings
);
550 * Get basic settings...
553 if ((val
= cupsGetOption(CUPS_SERVER_DEBUG_LOGGING
, num_settings
,
556 debug_logging
= atoi(val
);
558 if (debug_logging
== old_debug_logging
)
561 * No change to this setting...
570 DEBUG_printf(("1cupsAdminSetServerSettings: debug_logging=%d",
573 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ANY
, num_settings
, settings
)) != NULL
)
575 remote_any
= atoi(val
);
577 if (remote_any
== old_remote_any
)
580 * No change to this setting...
589 DEBUG_printf(("1cupsAdminSetServerSettings: remote_any=%d", remote_any
));
591 if ((val
= cupsGetOption(CUPS_SERVER_REMOTE_ADMIN
, num_settings
,
594 remote_admin
= atoi(val
);
596 if (remote_admin
== old_remote_admin
)
599 * No change to this setting...
608 DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d",
611 if ((val
= cupsGetOption(CUPS_SERVER_SHARE_PRINTERS
, num_settings
,
614 share_printers
= atoi(val
);
616 if (share_printers
== old_share_printers
)
619 * No change to this setting...
628 DEBUG_printf(("1cupsAdminSetServerSettings: share_printers=%d",
631 if ((val
= cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY
, num_settings
,
634 user_cancel_any
= atoi(val
);
636 if (user_cancel_any
== old_user_cancel_any
)
639 * No change to this setting...
642 user_cancel_any
= -1;
646 user_cancel_any
= -1;
648 DEBUG_printf(("1cupsAdminSetServerSettings: user_cancel_any=%d",
652 * Create a temporary file for the new cupsd.conf file...
655 if ((temp
= cupsTempFile2(tempfile
, sizeof(tempfile
))) == NULL
)
657 cupsFileClose(cupsd
);
662 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, NULL
, 0);
667 * Copy the old file to the new, making changes along the way...
670 cupsd_num_settings
= 0;
671 in_admin_location
= 0;
673 in_conf_location
= 0;
674 in_default_policy
= 0;
678 in_root_location
= 0;
680 wrote_admin_location
= 0;
682 wrote_conf_location
= 0;
683 wrote_log_location
= 0;
686 wrote_port_listen
= 0;
687 wrote_root_location
= 0;
690 if ((server_port_env
= getenv("SERVER_PORT")) != NULL
)
692 if ((server_port
= atoi(server_port_env
)) <= 0)
693 server_port
= ippPort();
696 server_port
= ippPort();
698 if (server_port
<= 0)
699 server_port
= IPP_PORT
;
701 while (cupsFileGetConf(cupsd
, line
, sizeof(line
), &value
, &linenum
))
703 if ((!_cups_strcasecmp(line
, "Port") || !_cups_strcasecmp(line
, "Listen")) &&
704 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
706 if (!wrote_port_listen
)
708 wrote_port_listen
= 1;
710 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
712 cupsFilePuts(temp
, "# Allow remote access\n");
713 cupsFilePrintf(temp
, "Port %d\n", server_port
);
717 cupsFilePuts(temp
, "# Only listen for connections from the local "
719 cupsFilePrintf(temp
, "Listen localhost:%d\n", server_port
);
722 #ifdef CUPS_DEFAULT_DOMAINSOCKET
723 if ((!value
|| strcmp(CUPS_DEFAULT_DOMAINSOCKET
, value
)) &&
724 !access(CUPS_DEFAULT_DOMAINSOCKET
, 0))
725 cupsFilePuts(temp
, "Listen " CUPS_DEFAULT_DOMAINSOCKET
"\n");
726 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
728 else if (value
&& value
[0] == '/'
729 #ifdef CUPS_DEFAULT_DOMAINSOCKET
730 && strcmp(CUPS_DEFAULT_DOMAINSOCKET
, value
)
731 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
733 cupsFilePrintf(temp
, "Listen %s\n", value
);
735 else if ((!_cups_strcasecmp(line
, "Browsing") ||
736 !_cups_strcasecmp(line
, "BrowseLocalProtocols")) &&
741 int new_share_printers
= (share_printers
> 0 ||
742 (share_printers
== -1 &&
743 old_share_printers
> 0));
747 if (new_share_printers
)
749 const char *localp
= cupsGetOption("BrowseLocalProtocols",
750 num_settings
, settings
);
752 if (!localp
|| !localp
[0])
753 localp
= cupsGetOption("BrowseLocalProtocols", cupsd_num_settings
,
756 cupsFilePuts(temp
, "# Share local printers on the local network.\n");
757 cupsFilePuts(temp
, "Browsing On\n");
760 localp
= CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS
;
762 cupsFilePrintf(temp
, "BrowseLocalProtocols %s\n", localp
);
764 cupsd_num_settings
= cupsAddOption("BrowseLocalProtocols", localp
,
770 cupsFilePuts(temp
, "# Disable printer sharing.\n");
771 cupsFilePuts(temp
, "Browsing Off\n");
775 else if (!_cups_strcasecmp(line
, "LogLevel") && debug_logging
>= 0)
782 "# Show troubleshooting information in error_log.\n");
783 cupsFilePuts(temp
, "LogLevel debug\n");
787 cupsFilePuts(temp
, "# Show general information in error_log.\n");
788 cupsFilePuts(temp
, "LogLevel " CUPS_DEFAULT_LOG_LEVEL
"\n");
791 else if (!_cups_strcasecmp(line
, "<Policy"))
793 in_default_policy
= !_cups_strcasecmp(value
, "default");
796 cupsFilePrintf(temp
, "%s %s>\n", line
, value
);
799 else if (!_cups_strcasecmp(line
, "</Policy>"))
802 if (!wrote_policy
&& in_default_policy
)
806 if (!user_cancel_any
)
807 cupsFilePuts(temp
, " # Only the owner or an administrator can "
809 " <Limit Cancel-Job>\n"
810 " Order deny,allow\n"
811 " Require user @OWNER "
812 CUPS_DEFAULT_PRINTOPERATOR_AUTH
"\n"
817 in_default_policy
= 0;
819 cupsFilePuts(temp
, "</Policy>\n");
821 else if (!_cups_strcasecmp(line
, "<Location"))
825 if (!strcmp(value
, "/admin"))
826 in_admin_location
= 1;
827 else if (!strcmp(value
, "/admin/conf"))
828 in_conf_location
= 1;
829 else if (!strcmp(value
, "/admin/log"))
831 else if (!strcmp(value
, "/"))
832 in_root_location
= 1;
834 cupsFilePrintf(temp
, "%s %s>\n", line
, value
);
836 else if (!_cups_strcasecmp(line
, "</Location>"))
840 if (in_admin_location
&& remote_admin
>= 0)
842 wrote_admin_location
= 1;
845 cupsFilePuts(temp
, " # Allow remote administration...\n");
846 else if (remote_admin
== 0)
847 cupsFilePuts(temp
, " # Restrict access to the admin pages...\n");
849 cupsFilePuts(temp
, " Order allow,deny\n");
852 cupsFilePrintf(temp
, " Allow %s\n",
853 remote_any
> 0 ? "all" : "@LOCAL");
855 else if (in_conf_location
&& remote_admin
>= 0)
857 wrote_conf_location
= 1;
860 cupsFilePuts(temp
, " # Allow remote access to the configuration "
863 cupsFilePuts(temp
, " # Restrict access to the configuration "
866 cupsFilePuts(temp
, " Order allow,deny\n");
869 cupsFilePrintf(temp
, " Allow %s\n",
870 remote_any
> 0 ? "all" : "@LOCAL");
872 else if (in_log_location
&& remote_admin
>= 0)
874 wrote_log_location
= 1;
877 cupsFilePuts(temp
, " # Allow remote access to the log "
880 cupsFilePuts(temp
, " # Restrict access to the log "
883 cupsFilePuts(temp
, " Order allow,deny\n");
886 cupsFilePrintf(temp
, " Allow %s\n",
887 remote_any
> 0 ? "all" : "@LOCAL");
889 else if (in_root_location
&&
890 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
892 wrote_root_location
= 1;
894 if (remote_admin
> 0 && share_printers
> 0)
895 cupsFilePuts(temp
, " # Allow shared printing and remote "
896 "administration...\n");
897 else if (remote_admin
> 0)
898 cupsFilePuts(temp
, " # Allow remote administration...\n");
899 else if (share_printers
> 0)
900 cupsFilePuts(temp
, " # Allow shared printing...\n");
901 else if (remote_any
> 0)
902 cupsFilePuts(temp
, " # Allow remote access...\n");
904 cupsFilePuts(temp
, " # Restrict access to the server...\n");
906 cupsFilePuts(temp
, " Order allow,deny\n");
908 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
909 cupsFilePrintf(temp
, " Allow %s\n",
910 remote_any
> 0 ? "all" : "@LOCAL");
913 in_admin_location
= 0;
914 in_conf_location
= 0;
916 in_root_location
= 0;
918 cupsFilePuts(temp
, "</Location>\n");
920 else if (!_cups_strcasecmp(line
, "<Limit"))
922 if (in_default_policy
)
925 * See if the policy limit is for the Cancel-Job operation...
928 char *valptr
; /* Pointer into value */
931 if (!_cups_strcasecmp(value
, "cancel-job") && user_cancel_any
>= 0)
934 * Don't write anything for this limit section...
941 cupsFilePrintf(temp
, "%*s%s", indent
, "", line
);
945 for (valptr
= value
; *valptr
&& !_cups_isspace(*valptr
); valptr
++);
950 if (!_cups_strcasecmp(value
, "cancel-job") && user_cancel_any
>= 0)
953 * Write everything except for this definition...
959 cupsFilePrintf(temp
, " %s", value
);
961 for (value
= valptr
; _cups_isspace(*value
); value
++);
964 cupsFilePuts(temp
, ">\n");
968 cupsFilePrintf(temp
, "%*s%s %s>\n", indent
, "", line
, value
);
972 else if (!_cups_strcasecmp(line
, "</Limit>") && in_cancel_job
)
976 if (in_cancel_job
== 1)
977 cupsFilePuts(temp
, " </Limit>\n");
981 if (!user_cancel_any
)
982 cupsFilePuts(temp
, " # Only the owner or an administrator can cancel "
984 " <Limit Cancel-Job>\n"
985 " Order deny,allow\n"
986 " Require user @OWNER "
987 CUPS_DEFAULT_PRINTOPERATOR_AUTH
"\n"
992 else if ((((in_admin_location
|| in_conf_location
|| in_root_location
) &&
993 (remote_admin
>= 0 || remote_any
>= 0)) ||
994 (in_root_location
&& share_printers
>= 0)) &&
995 (!_cups_strcasecmp(line
, "Allow") || !_cups_strcasecmp(line
, "Deny") ||
996 !_cups_strcasecmp(line
, "Order")))
998 else if (in_cancel_job
== 2)
1000 else if (line
[0] == '<')
1004 cupsFilePrintf(temp
, "%*s%s %s>\n", indent
, "", line
, value
);
1012 cupsFilePrintf(temp
, "%*s%s\n", indent
, "", line
);
1015 else if (!in_policy
&& !in_location
&&
1016 (val
= cupsGetOption(line
, num_settings
, settings
)) != NULL
)
1019 * Replace this directive's value with the new one...
1022 cupsd_num_settings
= cupsAddOption(line
, val
, cupsd_num_settings
,
1026 * Write the new value in its place, without indentation since we
1027 * only support setting root directives, not in sections...
1030 cupsFilePrintf(temp
, "%s %s\n", line
, val
);
1034 if (!in_policy
&& !in_location
)
1037 * Record the non-policy, non-location directives that we find
1038 * in the server settings, since we cache this info and record it
1039 * in cupsAdminGetServerSettings()...
1042 cupsd_num_settings
= cupsAddOption(line
, value
, cupsd_num_settings
,
1046 cupsFilePrintf(temp
, "%*s%s %s\n", indent
, "", line
, value
);
1049 cupsFilePrintf(temp
, "%*s%s\n", indent
, "", line
);
1053 * Write any missing info...
1056 if (!wrote_browsing
&& share_printers
>= 0)
1058 if (share_printers
> 0)
1060 cupsFilePuts(temp
, "# Share local printers on the local network.\n");
1061 cupsFilePuts(temp
, "Browsing On\n");
1065 cupsFilePuts(temp
, "# Disable printer sharing and shared printers.\n");
1066 cupsFilePuts(temp
, "Browsing Off\n");
1070 if (!wrote_loglevel
&& debug_logging
>= 0)
1074 cupsFilePuts(temp
, "# Show troubleshooting information in error_log.\n");
1075 cupsFilePuts(temp
, "LogLevel debug\n");
1079 cupsFilePuts(temp
, "# Show general information in error_log.\n");
1080 cupsFilePuts(temp
, "LogLevel " CUPS_DEFAULT_LOG_LEVEL
"\n");
1084 if (!wrote_port_listen
&&
1085 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
1087 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
1089 cupsFilePuts(temp
, "# Allow remote access\n");
1090 cupsFilePrintf(temp
, "Port %d\n", ippPort());
1095 "# Only listen for connections from the local machine.\n");
1096 cupsFilePrintf(temp
, "Listen localhost:%d\n", ippPort());
1099 #ifdef CUPS_DEFAULT_DOMAINSOCKET
1100 if (!access(CUPS_DEFAULT_DOMAINSOCKET
, 0))
1101 cupsFilePuts(temp
, "Listen " CUPS_DEFAULT_DOMAINSOCKET
"\n");
1102 #endif /* CUPS_DEFAULT_DOMAINSOCKET */
1105 if (!wrote_root_location
&&
1106 (remote_admin
>= 0 || remote_any
>= 0 || share_printers
>= 0))
1108 if (remote_admin
> 0 && share_printers
> 0)
1110 "# Allow shared printing and remote administration...\n");
1111 else if (remote_admin
> 0)
1112 cupsFilePuts(temp
, "# Allow remote administration...\n");
1113 else if (share_printers
> 0)
1114 cupsFilePuts(temp
, "# Allow shared printing...\n");
1115 else if (remote_any
> 0)
1116 cupsFilePuts(temp
, "# Allow remote access...\n");
1118 cupsFilePuts(temp
, "# Restrict access to the server...\n");
1120 cupsFilePuts(temp
, "<Location />\n"
1121 " Order allow,deny\n");
1123 if (remote_admin
> 0 || remote_any
> 0 || share_printers
> 0)
1124 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1126 cupsFilePuts(temp
, "</Location>\n");
1129 if (!wrote_admin_location
&& remote_admin
>= 0)
1132 cupsFilePuts(temp
, "# Allow remote administration...\n");
1134 cupsFilePuts(temp
, "# Restrict access to the admin pages...\n");
1136 cupsFilePuts(temp
, "<Location /admin>\n"
1137 " Order allow,deny\n");
1140 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1142 cupsFilePuts(temp
, "</Location>\n");
1145 if (!wrote_conf_location
&& remote_admin
>= 0)
1149 "# Allow remote access to the configuration files...\n");
1151 cupsFilePuts(temp
, "# Restrict access to the configuration files...\n");
1153 cupsFilePuts(temp
, "<Location /admin/conf>\n"
1154 " AuthType Default\n"
1155 " Require user @SYSTEM\n"
1156 " Order allow,deny\n");
1159 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1161 cupsFilePuts(temp
, "</Location>\n");
1164 if (!wrote_log_location
&& remote_admin
>= 0)
1168 "# Allow remote access to the log files...\n");
1170 cupsFilePuts(temp
, "# Restrict access to the log files...\n");
1172 cupsFilePuts(temp
, "<Location /admin/log>\n"
1173 " AuthType Default\n"
1174 " Require user @SYSTEM\n"
1175 " Order allow,deny\n");
1178 cupsFilePrintf(temp
, " Allow %s\n", remote_any
> 0 ? "all" : "@LOCAL");
1180 cupsFilePuts(temp
, "</Location>\n");
1183 if (!wrote_policy
&& user_cancel_any
>= 0)
1185 cupsFilePuts(temp
, "<Policy default>\n"
1186 " # Job-related operations must be done by the owner "
1187 "or an administrator...\n"
1188 " <Limit Send-Document Send-URI Hold-Job Release-Job "
1189 "Restart-Job Purge-Jobs Set-Job-Attributes "
1190 "Create-Job-Subscription Renew-Subscription "
1191 "Cancel-Subscription Get-Notifications Reprocess-Job "
1192 "Cancel-Current-Job Suspend-Current-Job Resume-Job "
1194 " Require user @OWNER @SYSTEM\n"
1195 " Order deny,allow\n"
1197 " # All administration operations require an "
1198 "administrator to authenticate...\n"
1199 " <Limit Pause-Printer Resume-Printer "
1200 "Set-Printer-Attributes Enable-Printer "
1201 "Disable-Printer Pause-Printer-After-Current-Job "
1202 "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer "
1203 "Activate-Printer Restart-Printer Shutdown-Printer "
1204 "Startup-Printer Promote-Job Schedule-Job-After "
1205 "CUPS-Add-Printer CUPS-Delete-Printer "
1206 "CUPS-Add-Class CUPS-Delete-Class "
1207 "CUPS-Accept-Jobs CUPS-Reject-Jobs "
1208 "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n"
1209 " AuthType Default\n"
1210 " Require user @SYSTEM\n"
1211 " Order deny,allow\n"
1214 if (!user_cancel_any
)
1215 cupsFilePuts(temp
, " # Only the owner or an administrator can cancel "
1217 " <Limit Cancel-Job>\n"
1218 " Order deny,allow\n"
1219 " Require user @OWNER "
1220 CUPS_DEFAULT_PRINTOPERATOR_AUTH
"\n"
1223 cupsFilePuts(temp
, " <Limit All>\n"
1224 " Order deny,allow\n"
1229 for (i
= num_settings
, setting
= settings
; i
> 0; i
--, setting
++)
1230 if (setting
->name
[0] != '_' &&
1231 _cups_strcasecmp(setting
->name
, "Listen") &&
1232 _cups_strcasecmp(setting
->name
, "Port") &&
1233 !cupsGetOption(setting
->name
, cupsd_num_settings
, cupsd_settings
))
1236 * Add this directive to the list of directives we have written...
1239 cupsd_num_settings
= cupsAddOption(setting
->name
, setting
->value
,
1240 cupsd_num_settings
, &cupsd_settings
);
1243 * Write the new value, without indentation since we only support
1244 * setting root directives, not in sections...
1247 cupsFilePrintf(temp
, "%s %s\n", setting
->name
, setting
->value
);
1250 cupsFileClose(cupsd
);
1251 cupsFileClose(temp
);
1254 * Upload the configuration file to the server...
1257 status
= cupsPutFile(http
, "/admin/conf/cupsd.conf", tempfile
);
1259 if (status
== HTTP_STATUS_CREATED
)
1262 * Updated OK, add the basic settings...
1265 if (debug_logging
>= 0)
1266 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_DEBUG_LOGGING
,
1267 debug_logging
? "1" : "0",
1268 cupsd_num_settings
, &cupsd_settings
);
1270 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_DEBUG_LOGGING
,
1271 old_debug_logging
? "1" : "0",
1272 cupsd_num_settings
, &cupsd_settings
);
1274 if (remote_admin
>= 0)
1275 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ADMIN
,
1276 remote_admin
? "1" : "0",
1277 cupsd_num_settings
, &cupsd_settings
);
1279 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ADMIN
,
1280 old_remote_admin
? "1" : "0",
1281 cupsd_num_settings
, &cupsd_settings
);
1283 if (remote_any
>= 0)
1284 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ANY
,
1285 remote_any
? "1" : "0",
1286 cupsd_num_settings
, &cupsd_settings
);
1288 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_REMOTE_ANY
,
1289 old_remote_any
? "1" : "0",
1290 cupsd_num_settings
, &cupsd_settings
);
1292 if (share_printers
>= 0)
1293 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_SHARE_PRINTERS
,
1294 share_printers
? "1" : "0",
1295 cupsd_num_settings
, &cupsd_settings
);
1297 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_SHARE_PRINTERS
,
1298 old_share_printers
? "1" : "0",
1299 cupsd_num_settings
, &cupsd_settings
);
1301 if (user_cancel_any
>= 0)
1302 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY
,
1303 user_cancel_any
? "1" : "0",
1304 cupsd_num_settings
, &cupsd_settings
);
1306 cupsd_num_settings
= cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY
,
1307 old_user_cancel_any
? "1" : "0",
1308 cupsd_num_settings
, &cupsd_settings
);
1311 * Save the new values...
1314 invalidate_cupsd_cache(cg
);
1316 cg
->cupsd_num_settings
= cupsd_num_settings
;
1317 cg
->cupsd_settings
= cupsd_settings
;
1318 cg
->cupsd_update
= time(NULL
);
1320 httpGetHostname(http
, cg
->cupsd_hostname
, sizeof(cg
->cupsd_hostname
));
1323 cupsFreeOptions(cupsd_num_settings
, cupsd_settings
);
1326 * Remote our temp files and return...
1334 return (status
== HTTP_STATUS_CREATED
);
1339 * 'get_cupsd_conf()' - Get the current cupsd.conf file.
1342 static http_status_t
/* O - Status of request */
1344 http_t
*http
, /* I - Connection to server */
1345 _cups_globals_t
*cg
, /* I - Global data */
1346 time_t last_update
, /* I - Last update time for file */
1347 char *name
, /* I - Filename buffer */
1348 size_t namesize
, /* I - Size of filename buffer */
1349 int *remote
) /* O - Remote file? */
1351 int fd
; /* Temporary file descriptor */
1353 struct stat info
; /* cupsd.conf file information */
1355 http_status_t status
; /* Status of getting cupsd.conf */
1356 char host
[HTTP_MAX_HOST
]; /* Hostname for connection */
1360 * See if we already have the data we need...
1363 httpGetHostname(http
, host
, sizeof(host
));
1365 if (_cups_strcasecmp(cg
->cupsd_hostname
, host
))
1366 invalidate_cupsd_cache(cg
);
1368 snprintf(name
, namesize
, "%s/cupsd.conf", cg
->cups_serverroot
);
1372 if (!_cups_strcasecmp(host
, "localhost") && !access(name
, R_OK
))
1375 * Read the local file rather than using HTTP...
1378 if (stat(name
, &info
))
1380 char message
[1024]; /* Message string */
1383 snprintf(message
, sizeof(message
),
1384 _cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")),
1385 name
, strerror(errno
));
1386 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, message
, 0);
1390 return (HTTP_STATUS_SERVER_ERROR
);
1392 else if (last_update
&& info
.st_mtime
<= last_update
)
1393 status
= HTTP_STATUS_NOT_MODIFIED
;
1395 status
= HTTP_STATUS_OK
;
1398 #endif /* !_WIN32 */
1401 * Read cupsd.conf via a HTTP GET request...
1404 if ((fd
= cupsTempFd(name
, (int)namesize
)) < 0)
1408 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, NULL
, 0);
1410 invalidate_cupsd_cache(cg
);
1412 return (HTTP_STATUS_SERVER_ERROR
);
1417 httpClearFields(http
);
1420 httpSetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
,
1421 httpGetDateString(last_update
));
1423 status
= cupsGetFd(http
, "/admin/conf/cupsd.conf", fd
);
1427 if (status
!= HTTP_STATUS_OK
)
1439 * 'invalidate_cupsd_cache()' - Invalidate the cached cupsd.conf settings.
1443 invalidate_cupsd_cache(
1444 _cups_globals_t
*cg
) /* I - Global data */
1446 cupsFreeOptions(cg
->cupsd_num_settings
, cg
->cupsd_settings
);
1448 cg
->cupsd_hostname
[0] = '\0';
1449 cg
->cupsd_update
= 0;
1450 cg
->cupsd_num_settings
= 0;
1451 cg
->cupsd_settings
= NULL
;