/*
- * "$Id: ipp.c 6739 2007-07-26 19:30:03Z mike $"
+ * "$Id: ipp.c 7014 2007-10-10 21:57:43Z mike $"
*
* IPP routines for the Common UNIX Printing System (CUPS) scheduler.
*
* get_default() - Get the default destination.
* get_devices() - Get the list of available devices on the
* local system.
+ * get_document() - Get a copy of a job file.
* get_job_attrs() - Get job attributes.
* get_jobs() - Get a list of jobs for the specified printer.
* get_notifications() - Get events for a subscription.
#include "cupsd.h"
-#ifdef HAVE_KRB5_H
-# include <krb5.h>
-#endif /* HAVE_KRB5_H */
-
#ifdef HAVE_LIBPAPER
# include <paper.h>
#endif /* HAVE_LIBPAPER */
static void delete_printer(cupsd_client_t *con, ipp_attribute_t *uri);
static void get_default(cupsd_client_t *con);
static void get_devices(cupsd_client_t *con);
+static void get_document(cupsd_client_t *con, ipp_attribute_t *uri);
static void get_jobs(cupsd_client_t *con, ipp_attribute_t *uri);
static void get_job_attrs(cupsd_client_t *con, ipp_attribute_t *uri);
static void get_notifications(cupsd_client_t *con);
ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
"attributes-natural-language", NULL, DefaultLanguage);
- if (!charset || !language ||
- (!uri &&
- con->request->request.op.operation_id != CUPS_GET_DEFAULT &&
- con->request->request.op.operation_id != CUPS_GET_PRINTERS &&
- con->request->request.op.operation_id != CUPS_GET_CLASSES &&
- con->request->request.op.operation_id != CUPS_GET_DEVICES &&
- con->request->request.op.operation_id != CUPS_GET_PPDS))
+ if (charset &&
+ strcasecmp(charset->values[0].string.text, "us-ascii") &&
+ strcasecmp(charset->values[0].string.text, "utf-8"))
+ {
+ /*
+ * Bad character set...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unsupported character set \"%s\"!",
+ charset->values[0].string.text);
+ cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL,
+ "%04X %s Unsupported attributes-charset value \"%s\"",
+ IPP_CHARSET, con->http.hostname,
+ charset->values[0].string.text);
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Unsupported character set \"%s\"!"),
+ charset->values[0].string.text);
+ }
+ else if (!charset || !language ||
+ (!uri &&
+ con->request->request.op.operation_id != CUPS_GET_DEFAULT &&
+ con->request->request.op.operation_id != CUPS_GET_PRINTERS &&
+ con->request->request.op.operation_id != CUPS_GET_CLASSES &&
+ con->request->request.op.operation_id != CUPS_GET_DEVICES &&
+ con->request->request.op.operation_id != CUPS_GET_PPDS))
{
/*
* Return an error, since attributes-charset,
get_devices(con);
break;
+ case CUPS_GET_DOCUMENT :
+ get_document(con, uri);
+ break;
+
case CUPS_GET_PPD :
get_ppd(con, uri);
break;
return;
}
- /*
- * Check policy...
- */
-
- if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
- {
- send_http_error(con, status, NULL);
- return;
- }
-
/*
* See if the class already exists; if not, create a new class...
*/
}
/*
- * No, add the pclass...
+ * No, check the default policy and then add the class...
*/
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
pclass = cupsdAddClass(resource + 9);
modify = 0;
}
else if (pclass->type & CUPS_PRINTER_IMPLICIT)
{
/*
- * Rename the implicit class to "AnyClass" or remove it...
+ * Check the default policy, then rename the implicit class to "AnyClass"
+ * or remove it...
*/
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
if (ImplicitAnyClasses)
{
snprintf(newname, sizeof(newname), "Any%s", resource + 9);
else if (pclass->type & CUPS_PRINTER_DISCOVERED)
{
/*
- * Rename the remote class to "Class"...
+ * Check the default policy, then rename the remote class to "Class"...
*/
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
snprintf(newname, sizeof(newname), "%s@%s", resource + 9, pclass->hostname);
cupsdRenamePrinter(pclass, newname);
pclass = cupsdAddClass(resource + 9);
modify = 0;
}
+ else if ((status = cupsdCheckPolicy(pclass->op_policy_ptr, con,
+ NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, pclass);
+ return;
+ }
else
modify = 1;
cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))",
con, con->http.fd, printer, printer->name,
- filetype, filetype->super, filetype->type);
+ filetype, filetype ? filetype->super : "none",
+ filetype ? filetype->type : "none");
/*
* Check remote printing to non-shared printer...
return;
}
- /*
- * Check policy...
- */
-
- if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
- {
- send_http_error(con, status, NULL);
- return;
- }
-
/*
* See if the printer already exists; if not, create a new printer...
*/
}
/*
- * No, add the printer...
+ * No, check the default policy then add the printer...
*/
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
printer = cupsdAddPrinter(resource + 10);
modify = 0;
}
else if (printer->type & CUPS_PRINTER_IMPLICIT)
{
/*
- * Rename the implicit printer to "AnyPrinter" or delete it...
+ * Check the default policy, then rename the implicit printer to
+ * "AnyPrinter" or delete it...
*/
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
if (ImplicitAnyClasses)
{
snprintf(newname, sizeof(newname), "Any%s", resource + 10);
else if (printer->type & CUPS_PRINTER_DISCOVERED)
{
/*
- * Rename the remote printer to "Printer@server"...
+ * Check the default policy, then rename the remote printer to
+ * "Printer@server"...
*/
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
snprintf(newname, sizeof(newname), "%s@%s", resource + 10,
printer->hostname);
cupsdRenamePrinter(printer, newname);
printer = cupsdAddPrinter(resource + 10);
modify = 0;
}
+ else if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
+ NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, printer);
+ return;
+ }
else
modify = 1;
* Do we have a valid device URI?
*/
+ http_uri_status_t uri_status; /* URI separation status */
+
+
need_restart_job = 1;
- httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, scheme,
- sizeof(scheme), username, sizeof(username), host,
- sizeof(host), &port, resource, sizeof(resource));
+ uri_status = httpSeparateURI(HTTP_URI_CODING_ALL,
+ attr->values[0].string.text,
+ scheme, sizeof(scheme),
+ username, sizeof(username),
+ host, sizeof(host), &port,
+ resource, sizeof(resource));
+
+ if (uri_status < HTTP_URI_OK)
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE, _("Bad device-uri \"%s\"!"),
+ attr->values[0].string.text);
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "add_printer: httpSeparateURI returned %d", uri_status);
+ return;
+ }
if (!strcmp(scheme, "file"))
{
need_restart_job = 1;
supported = ippFindAttribute(printer->attrs, "port-monitor-supported",
- IPP_TAG_KEYWORD);
+ IPP_TAG_NAME);
for (i = 0; i < supported->num_values; i ++)
if (!strcmp(supported->values[i].string.text,
attr->values[0].string.text))
if (!con->username[0] && !auth_info)
{
- send_ipp_status(con, IPP_NOT_AUTHORIZED,
- _("No authentication information provided!"));
+ cupsd_printer_t *printer; /* Job destination */
+
+
+ /*
+ * No auth data. If we need to authenticate via Kerberos, send a
+ * HTTP auth challenge, otherwise just return an IPP error...
+ */
+
+ printer = cupsdFindDest(job->dest);
+
+ if (printer && printer->num_auth_info_required > 0 &&
+ !strcmp(printer->auth_info_required[0], "negotiate"))
+ send_http_error(con, HTTP_UNAUTHORIZED, printer);
+ else
+ send_ipp_status(con, IPP_NOT_AUTHORIZED,
+ _("No authentication information provided!"));
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
cupsd_job_t *job; /* Job information */
cups_ptype_t dtype; /* Destination type (printer/class) */
cupsd_printer_t *printer; /* Printer data */
+ int purge; /* Purge the job? */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_job(%p[%d], %s)", con,
jobid = atoi(resource + 6);
}
+ /*
+ * Look for the "purge-job" attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "purge-job",
+ IPP_TAG_BOOLEAN)) != NULL)
+ purge = attr->values[0].boolean;
+ else
+ purge = 0;
+
/*
* See if the job exists...
*/
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
* we can't cancel...
*/
- if (job->state_value >= IPP_JOB_CANCELED)
+ if (job->state_value >= IPP_JOB_CANCELED && !purge)
{
switch (job->state_value)
{
* Cancel the job and return...
*/
- cupsdCancelJob(job, 0, IPP_JOB_CANCELED);
+ cupsdCancelJob(job, purge, IPP_JOB_CANCELED);
cupsdCheckJobs();
- cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Canceled by \"%s\".", jobid,
- username);
+ if (purge)
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Purged by \"%s\".", jobid,
+ username);
+ else
+ cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Canceled by \"%s\".", jobid,
+ username);
con->response->request.status.status_code = IPP_OK;
}
con->servername, con->serverport, "/jobs/%d",
job->id);
+ if (!ra || cupsArrayFind(ra, "document-count"))
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "document-count", job->num_files);
+
if (!ra || cupsArrayFind(ra, "job-more-info"))
ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
"job-more-info", NULL, job_uri);
}
+/*
+ * 'get_document()' - Get a copy of a job file.
+ */
+
+static void
+get_document(cupsd_client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job URI */
+{
+ http_status_t status; /* Policy status */
+ ipp_attribute_t *attr; /* Current attribute */
+ int jobid; /* Job ID */
+ int docnum; /* Document number */
+ cupsd_job_t *job; /* Current job */
+ char method[HTTP_MAX_URI], /* Method portion of URI */
+ username[HTTP_MAX_URI], /* Username portion of URI */
+ host[HTTP_MAX_URI], /* Host portion of URI */
+ resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ int port; /* Port portion of URI */
+ char filename[1024], /* Filename for document */
+ format[1024]; /* Format for document */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_document(%p[%d], %s)", con,
+ con->http.fd, uri->values[0].string.text);
+
+ /*
+ * See if we have a job URI or a printer URI...
+ */
+
+ if (!strcmp(uri->name, "printer-uri"))
+ {
+ /*
+ * Got a printer URI; see if we also have a job-id attribute...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "job-id",
+ IPP_TAG_INTEGER)) == NULL)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Got a printer-uri attribute but no job-id!"));
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, method,
+ sizeof(method), username, sizeof(username), host,
+ sizeof(host), &port, resource, sizeof(resource));
+
+ if (strncmp(resource, "/jobs/", 6))
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Bad job-uri attribute \"%s\"!"),
+ uri->values[0].string.text);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = cupsdFindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid);
+ return;
+ }
+
+ /*
+ * Check policy...
+ */
+
+ if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ {
+ send_http_error(con, status, NULL);
+ return;
+ }
+
+ /*
+ * Get the document number...
+ */
+
+ if ((attr = ippFindAttribute(con->request, "document-number",
+ IPP_TAG_INTEGER)) == NULL)
+ {
+ send_ipp_status(con, IPP_BAD_REQUEST,
+ _("Missing document-number attribute!"));
+ return;
+ }
+
+ if ((docnum = attr->values[0].integer) < 1 || docnum > job->num_files ||
+ attr->num_values > 1)
+ {
+ send_ipp_status(con, IPP_NOT_FOUND, _("Document %d not found in job %d."),
+ docnum, jobid);
+ return;
+ }
+
+ snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, jobid,
+ docnum);
+ if ((con->file = open(filename, O_RDONLY)) == -1)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to open document %d in job %d - %s", docnum, jobid,
+ strerror(errno));
+ send_ipp_status(con, IPP_NOT_FOUND,
+ _("Unable to open document %d in job %d!"), docnum, jobid);
+ return;
+ }
+
+ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);
+
+ cupsdLoadJob(job);
+
+ snprintf(format, sizeof(format), "%s/%s", job->filetypes[docnum - 1]->super,
+ job->filetypes[docnum - 1]->type);
+
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
+ NULL, format);
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "document-number",
+ docnum);
+ if ((attr = ippFindAttribute(job->attrs, "document-name",
+ IPP_TAG_NAME)) != NULL)
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_NAME, "document-name",
+ NULL, attr->values[0].string.text);
+}
+
+
/*
* 'get_job_attrs()' - Get job attributes.
*/
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: job->id = %d", job->id);
+ if (!job->dest || !job->username)
+ cupsdLoadJob(job);
+
+ if (!job->dest || !job->username)
+ continue;
+
if ((dest && strcmp(job->dest, dest)) &&
(!job->printer || !dest || strcmp(job->printer->name, dest)))
continue;
if ((status = cupsdCheckPolicy(dest->op_policy_ptr, con, NULL)) != HTTP_OK)
{
- send_http_error(con, status, NULL);
+ send_http_error(con, status, dest);
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
save_krb5_creds(cupsd_client_t *con, /* I - Client connection */
cupsd_job_t *job) /* I - Job */
{
- krb5_context krb_context; /* Kerberos context */
- krb5_ccache ccache; /* Credentials cache */
- OM_uint32 major_status, /* Major status code */
- minor_status; /* Minor status code */
-
+# if !defined(HAVE_KRB5_CC_NEW_UNIQUE) && !defined(HAVE_HEIMDAL)
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "Sorry, your version of Kerberos does not support delegated "
+ "credentials!");
+ return;
-# ifdef __APPLE__
- /*
- * If the weak-linked GSSAPI/Kerberos library is not present, don't try
- * to use it...
- */
+# else
+ krb5_error_code error; /* Kerberos error code */
+ OM_uint32 major_status, /* Major status code */
+ minor_status; /* Minor status code */
+ krb5_principal principal; /* Kerberos principal */
- if (krb5_init_context == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "save_krb5_creds: GSSAPI/Kerberos framework is not "
- "present");
- return;
- }
-# endif /* __APPLE__ */
+# ifdef __APPLE__
/*
- * Setup a cached context for the job filters to use...
+ * If the weak-linked GSSAPI/Kerberos library is not present, don't try
+ * to use it...
*/
- if (krb5_init_context(&krb_context))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context");
+ if (krb5_init_context == NULL)
return;
- }
+# endif /* __APPLE__ */
/*
* We MUST create a file-based cache because memory-based caches are
* only valid for the current process/address space.
- */
+ *
+ * Due to various bugs/features in different versions of Kerberos, we
+ * need either the krb5_cc_new_unique() function or Heimdal's version
+ * of krb5_cc_gen_new() to create a new FILE: credential cache that
+ * can be passed to the backend. These functions create a temporary
+ * file (typically in /tmp) containing the cached credentials, which
+ * are removed when we have successfully printed a job.
+ */
+
+# ifdef HAVE_KRB5_CC_NEW_UNIQUE
+ if ((error = krb5_cc_new_unique(KerberosContext, "FILE", NULL,
+ &(job->ccache))) != 0)
+# else /* HAVE_HEIMDAL */
+ if ((error = krb5_cc_gen_new(KerberosContext, &krb5_fcc_ops,
+ &(job->ccache))) != 0)
+# endif /* HAVE_KRB5_CC_NEW_UNIQUE */
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to create new credentials cache (%d/%s)",
+ error, strerror(errno));
+ job->ccache = NULL;
+ return;
+ }
-# ifdef HAVE_KRB5_CC_RESOLVE
- if (krb5_cc_resolve(krb_context, "FILE:", &ccache))
-# elif defined(HAVE_HEIMDAL)
- if (krb5_cc_gen_new(krb_context, &krb5_fcc_ops, &ccache))
-# else
- if (krb5_cc_gen_new(krb_context, &ccache))
-# endif /* HAVE_HEIMDAL */
+ if ((error = krb5_parse_name(KerberosContext, con->username, &principal)) != 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to parse kerberos username (%d/%s)",
+ error, strerror(errno));
+ krb5_cc_destroy(KerberosContext, job->ccache);
+ job->ccache = NULL;
+ return;
+ }
+
+ if ((error = krb5_cc_initialize(KerberosContext, job->ccache, principal)))
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create new credentials");
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to initialize credentials cache (%d/%s)", error,
+ strerror(errno));
+ krb5_cc_destroy(KerberosContext, job->ccache);
+ krb5_free_principal(KerberosContext, principal);
+ job->ccache = NULL;
return;
}
+ krb5_free_principal(KerberosContext, principal);
+
+ /*
+ * Copy the user's credentials to the new cache file...
+ */
+
major_status = gss_krb5_copy_ccache(&minor_status, con->gss_delegated_cred,
- ccache);
+ job->ccache);
if (GSS_ERROR(major_status))
{
cupsdLogGSSMessage(CUPSD_LOG_ERROR, major_status, minor_status,
"Unable to import client credentials cache");
- krb5_cc_destroy(krb_context, ccache);
+ krb5_cc_destroy(KerberosContext, job->ccache);
+ job->ccache = NULL;
return;
}
+ /*
+ * Add the KRB5CCNAME environment variable to the job so that the
+ * backend can use the credentials when printing.
+ */
+
cupsdSetStringf(&(job->ccname), "KRB5CCNAME=FILE:%s",
- krb5_cc_get_name(krb_context, ccache));
+ krb5_cc_get_name(KerberosContext, job->ccache));
cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Job %d] save_krb5_creds: %s", job->id,
job->ccname);
-
- krb5_cc_close(krb_context, ccache);
+# endif /* HAVE_KRB5_CC_NEW_UNIQUE || HAVE_HEIMDAL */
}
#endif /* HAVE_GSSAPI && HAVE_KRB5_H */
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
printer && printer->num_auth_info_required > 0 &&
!strcmp(printer->auth_info_required[0], "negotiate"))
cupsdSendError(con, status, AUTH_NEGOTIATE);
+ else if (printer)
+ {
+ char resource[HTTP_MAX_URI]; /* Resource portion of URI */
+ cupsd_location_t *auth; /* Pointer to authentication element */
+
+
+ if (printer->type & CUPS_PRINTER_CLASS)
+ snprintf(resource, sizeof(resource), "/classes/%s", printer->name);
+ else
+ snprintf(resource, sizeof(resource), "/printers/%s", printer->name);
+
+ if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
+ auth->type == AUTH_NONE)
+ auth = cupsdFindPolicyOp(printer->op_policy_ptr, IPP_PRINT_JOB);
+
+ cupsdSendError(con, status, auth ? auth->type : AUTH_NONE);
+ }
else
cupsdSendError(con, status, AUTH_NONE);
if (!validate_user(job, con, job->username, username, sizeof(username)))
{
- send_http_error(con, HTTP_UNAUTHORIZED, NULL);
+ send_http_error(con, HTTP_UNAUTHORIZED, cupsdFindDest(job->dest));
return;
}
/*
- * End of "$Id: ipp.c 6739 2007-07-26 19:30:03Z mike $".
+ * End of "$Id: ipp.c 7014 2007-10-10 21:57:43Z mike $".
*/