+/*
+ * 'authenticate_job()' - Set job authentication info.
+ */
+
+static void
+authenticate_job(client_t *con, /* I - Client connection */
+ ipp_attribute_t *uri) /* I - Job URI */
+{
+ ipp_attribute_t *attr; /* Job-id attribute */
+ int jobid; /* Job ID */
+ 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 */
+
+
+ LogMessage(L_DEBUG2, "authenticate_job(%p[%d], %s)\n", con, con->http.fd,
+ uri->values[0].string.text);
+
+ /*
+ * Start with "everything is OK" status...
+ */
+
+ con->response->request.status.status_code = IPP_OK;
+
+ /*
+ * 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)
+ {
+ LogMessage(L_ERROR, "authenticate_job: got a printer-uri attribute but no job-id!");
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = attr->values[0].integer;
+ }
+ else
+ {
+ /*
+ * Got a job URI; parse it to get the job ID...
+ */
+
+ httpSeparate(uri->values[0].string.text, method, username, host, &port, resource);
+
+ if (strncmp(resource, "/jobs/", 6))
+ {
+ /*
+ * Not a valid URI!
+ */
+
+ LogMessage(L_ERROR, "authenticate_job: bad job-uri attribute \'%s\'!\n",
+ uri->values[0].string.text);
+ send_ipp_error(con, IPP_BAD_REQUEST);
+ return;
+ }
+
+ jobid = atoi(resource + 6);
+ }
+
+ /*
+ * See if the job exists...
+ */
+
+ if ((job = FindJob(jobid)) == NULL)
+ {
+ /*
+ * Nope - return a "not found" error...
+ */
+
+ LogMessage(L_ERROR, "authenticate_job: job #%d doesn't exist!", jobid);
+ send_ipp_error(con, IPP_NOT_FOUND);
+ return;
+ }
+
+ /*
+ * See if the job has been completed...
+ */
+
+ if (job->state->values[0].integer != IPP_JOB_HELD)
+ {
+ /*
+ * Return a "not-possible" error...
+ */
+
+ LogMessage(L_ERROR, "authenticate_job: job #%d is not held for authentication!", jobid);
+ send_ipp_error(con, IPP_NOT_POSSIBLE);
+ return;
+ }
+
+ /*
+ * See if we have already authenticated...
+ */
+
+ if (!con->username[0])
+ {
+ send_ipp_error(con, IPP_NOT_AUTHORIZED);
+ return;
+ }
+
+ /*
+ * See if the job is owned by the requesting user...
+ */
+
+ if (!validate_user(job, con, job->username, username, sizeof(username)))
+ {
+ LogMessage(L_ERROR, "authenticate_job: \"%s\" not authorized to authenticate job id %d owned by \"%s\"!",
+ username, jobid, job->username);
+ send_ipp_error(con, IPP_FORBIDDEN);
+ return;
+ }
+
+ /*
+ * Save the authentication information for this job...
+ */
+
+ save_auth_info(con, job->id);
+
+ /*
+ * Reset the job-hold-until value to "no-hold"...
+ */
+
+ if ((attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_KEYWORD)) == NULL)
+ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+ if (attr != NULL)
+ {
+ attr->value_tag = IPP_TAG_KEYWORD;
+ SetString(&(attr->values[0].string.text), "no-hold");
+ }
+
+ /*
+ * Release the job and return...
+ */
+
+ ReleaseJob(jobid);
+
+ LogMessage(L_INFO, "Job %d was authenticated by \'%s\'.", jobid,
+ con->username);
+}
+
+