summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2014-02-13 16:51:08 +0100
committerSimon Rettberg2014-02-13 16:51:08 +0100
commit00c6bfdc44adcef4f800867489cef9ce16628290 (patch)
treeb74c81da22dbe53fc9554c653f93a00fc8889678
parentFix indentation (diff)
downloadprintergui-00c6bfdc44adcef4f800867489cef9ce16628290.tar.gz
printergui-00c6bfdc44adcef4f800867489cef9ce16628290.tar.xz
printergui-00c6bfdc44adcef4f800867489cef9ce16628290.zip
Add auth support for iprint via ipp14
ipp14 will not return CUPS_BACKEND_AUTH_REQUIRED but just fail, but luckily it tells you on stderr that it is "not authorized"... So we just check stderr of the real backend and act accordingly if we encounter such a message.
-rw-r--r--src/pwgui/main.cpp77
1 files changed, 76 insertions, 1 deletions
diff --git a/src/pwgui/main.cpp b/src/pwgui/main.cpp
index 5dc2060..dc14006 100644
--- a/src/pwgui/main.cpp
+++ b/src/pwgui/main.cpp
@@ -14,6 +14,7 @@
#include <limits.h>
#include <pwd.h>
#include <grp.h>
+#include <errno.h>
#define NAMELEN 400
#define BUFLEN 1000
@@ -33,6 +34,7 @@ static bool helper_getpiduid(char *user, char *title);
static bool helper_loadlpuser();
static void helper_dropprivs();
static void helper_copyenv();
+static char *helper_urlencode(char *s, char *enc);
int main(int argc, char *argv[])
{
@@ -182,11 +184,31 @@ int main(int argc, char *argv[])
static int run_backend(char *backend, char *uri, char *jobid, char *user, char *title, char *copies, char *options, char *file, char *password)
{
+ int pipefd[2];
+ pipe(pipefd);
pid_t pid = fork();
if (pid == 0) {
// Child
+ close(pipefd[0]); // close reading end
+ dup2(pipefd[1], 2); // send stderr to pipe
+ close(pipefd[1]); // no longer needed after dup
+ // Newer backend can read credentials from environment
if (user != NULL) setenv("AUTH_USERNAME", user, 1);
if (password != NULL) setenv("AUTH_PASSWORD", password, 1);
+ // For ipp14 (at least) we need to build a new URI with ://username:password@....
+ if (user != NULL && password != NULL && strncmp(uri, "ipp14", 5) == 0) {
+ char *newstr = (char*)malloc(strlen(uri) + strlen(user) * 3 + strlen(password) * 3 + 20);
+ char *ptr = newstr;
+ ptr += sprintf(ptr, "ipp14://");
+ ptr = helper_urlencode(user, ptr);
+ *ptr++ = ':';
+ ptr = helper_urlencode(password, ptr);
+ *ptr++ = '@';
+ ptr += sprintf(ptr, "%s", uri + 8); // TODO: If uri already contains credentials, skip over them (check if there's a @ before the first /, starting at index 8)
+ uri = newstr;
+ setenv("DEVICE_URI", uri, 1);
+ // Since we've already forked and execv anyways there's no need to clean up anything...
+ }
char *args[8];
args[0] = uri;
args[1] = jobid;
@@ -206,12 +228,39 @@ static int run_backend(char *backend, char *uri, char *jobid, char *user, char *
}
// Main - wait for it...
+ close(pipefd[1]); // close writing end
+ char buffer[BUFLEN];
+ bool needAuth = false;
+ int readlen = 0;
+ while ((readlen = read(pipefd[0], buffer, BUFLEN-1)) > 0) {
+ buffer[readlen] = '\0';
+ if (strstr(buffer, "Unable to get printer status (Unauthorized)!") != NULL) {
+ needAuth = true;
+ if (kill(pid, SIGTERM) < 0) {
+ fprintf(stderr, "ERROR: Sending kill1 to backend %d failed: %d\n", (int)pid, errno);
+ }
+ break;
+ }
+ }
+ close(pipefd[0]);
int status;
- waitpid(pid, &status, 0);
+ if (waitpid(pid, &status, WNOHANG) == 0) {
+ if (kill(pid, SIGKILL) == 0) {
+ // Try to reap zombie
+ sleep(1);
+ waitpid(pid, &status, WNOHANG);
+ }
+ }
+ if (needAuth) {
+ fprintf(stderr, "ERROR: Killed backend because of 'unauthorized' message (iprint crap?), trying with auth\n");
+ return CUPS_BACKEND_AUTH_REQUIRED;
+ }
if (!WIFEXITED(status)) {
fprintf(stderr, "ERROR: Running backend %s failed!\n", backend);
return CUPS_BACKEND_FAILED;
}
+ status = WEXITSTATUS(status);
+ if (status != CUPS_BACKEND_OK) fprintf(stderr, "ERROR: Backend returned %d\n", status);
return WEXITSTATUS(status);
}
@@ -314,3 +363,29 @@ static void helper_copyenv()
}
}
+/**
+ * Make sure enc is 3 times as large as s
+ */
+static char *helper_urlencode(char *source, char *enc)
+{
+ static char table[256] = {3};
+ int len;
+
+ if (table[0] == 3) {
+ int i;
+ for (i = 0; i < 256; i++) {
+ table[i] = (isalnum(i) || i == '~' || i == '-' || i == '.' || i == '_') ? i : 0;
+ }
+ }
+
+ unsigned char *s = (unsigned char*)source;
+ for (; *s != '\0'; s++) {
+ if (table[*s] != '\0') len = sprintf(enc, "%c", table[*s]);
+ else len = sprintf(enc, "%%%02X", *s);
+ enc += len;
+ }
+ *enc = '\0';
+
+ return enc;
+}
+