summaryrefslogtreecommitdiffstats
path: root/kdeprint/cups/cupsdconf2/cups-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'kdeprint/cups/cupsdconf2/cups-util.c')
-rw-r--r--kdeprint/cups/cupsdconf2/cups-util.c556
1 files changed, 556 insertions, 0 deletions
diff --git a/kdeprint/cups/cupsdconf2/cups-util.c b/kdeprint/cups/cupsdconf2/cups-util.c
new file mode 100644
index 000000000..cb6ddcf92
--- /dev/null
+++ b/kdeprint/cups/cupsdconf2/cups-util.c
@@ -0,0 +1,556 @@
+#include <cups/ipp.h>
+#include <cups/http.h>
+#include <cups/cups.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define CUPS_SERVERROOT "/etc/cups"
+static http_t *cups_server;
+static ipp_status_t last_error;
+static char authstring[HTTP_MAX_VALUE];
+static char pwdstring[33];
+static int cups_local_auth(http_t *http);
+
+const char* cupsGetConf( void );
+int cupsPutConf( const char* );
+
+const char * /* O - Filename for PPD file */
+cupsGetConf(void)
+{
+ int fd; /* PPD file */
+ int bytes; /* Number of bytes read */
+ char buffer[8192]; /* Buffer for file */
+ char resource[HTTP_MAX_URI]; /* Resource name */
+ const char *password; /* Password string */
+ char realm[HTTP_MAX_VALUE], /* realm="xyz" string */
+ nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */
+ plain[255], /* Plaintext username:password */
+ encode[512]; /* Encoded username:password */
+ http_status_t status; /* HTTP status from server */
+ char prompt[1024]; /* Prompt string */
+ int digest_tries; /* Number of tries with Digest */
+ static char filename[HTTP_MAX_URI]; /* Local filename */
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ const char *fqdn = 0;
+#else
+ char fqdn[ HTTP_MAX_URI ]; /* Server name buffer */
+#endif
+
+
+ /*
+ * Connect to the correct server as needed...
+ */
+
+ if ((cups_server = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return (NULL);
+ }
+
+ /*
+ * Get a temp file...
+ */
+
+ if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
+ {
+ /*
+ * Can't open file; close the server connection and return NULL...
+ */
+
+ httpFlush(cups_server);
+ httpClose(cups_server);
+ cups_server = NULL;
+ return (NULL);
+ }
+
+ /*
+ * And send a request to the HTTP server...
+ */
+
+ snprintf(resource, sizeof(resource), "/admin/conf/cupsd.conf");
+
+ digest_tries = 0;
+
+ do
+ {
+ httpClearFields(cups_server);
+ httpSetField(cups_server, HTTP_FIELD_HOST, cupsServer());
+ httpSetField(cups_server, HTTP_FIELD_AUTHORIZATION, authstring);
+
+ if (httpGet(cups_server, resource))
+ {
+ if (httpReconnect(cups_server))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+ else
+ {
+ status = HTTP_UNAUTHORIZED;
+ continue;
+ }
+ }
+
+ while ((status = httpUpdate(cups_server)) == HTTP_CONTINUE);
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ const char *www_authenticate;
+ fprintf(stderr,"cupsGetConf: unauthorized...\n");
+
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(cups_server);
+
+ /*
+ * See if we can do local authentication...
+ */
+
+ if (cups_local_auth(cups_server))
+ continue;
+
+ /*
+ * See if we should retry the current digest password...
+ */
+
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ www_authenticate = cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE];
+#else
+ www_authenticate = httpGetField( cups_server, HTTP_FIELD_WWW_AUTHENTICATE );
+#endif
+ if (strncmp(www_authenticate, "Basic", 5) == 0 ||
+ digest_tries > 1 || !pwdstring[0])
+ {
+ /*
+ * Nope - get a password from the user...
+ */
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ fqdn = cups_server->hostname;
+#else
+ httpGetHostname( cups_server, fqdn, sizeof( fqdn ) );
+#endif
+
+ snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(), fqdn );
+
+ if ((password = cupsGetPassword(prompt)) == NULL)
+ break;
+ if (!password[0])
+ break;
+
+ strncpy(pwdstring, password, sizeof(pwdstring) - 1);
+ pwdstring[sizeof(pwdstring) - 1] = '\0';
+
+ digest_tries = 0;
+ }
+ else
+ digest_tries ++;
+
+ /*
+ * Got a password; encode it for the server...
+ */
+
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ www_authenticate = cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE];
+#else
+ www_authenticate = httpGetField( cups_server, HTTP_FIELD_WWW_AUTHENTICATE );
+#endif
+ if (strncmp(www_authenticate, "Basic", 5) == 0)
+ {
+ /*
+ * Basic authentication...
+ */
+
+ snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), pwdstring);
+#if CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2
+ httpEncode64_2(encode, sizeof(encode), plain, sizeof(plain));
+#else
+ httpEncode64(encode, plain);
+#endif
+ snprintf(authstring, sizeof(authstring), "Basic %s", encode);
+ }
+ else
+ {
+ /*
+ * Digest authentication...
+ */
+
+ httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
+ httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
+
+ httpMD5(cupsUser(), realm, pwdstring, encode);
+ httpMD5Final(nonce, "GET", resource, encode);
+ snprintf(authstring, sizeof(authstring),
+ "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
+ "response=\"%s\"", cupsUser(), realm, nonce, encode);
+ }
+
+ continue;
+ }
+#ifdef HAVE_LIBSSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(cups_server);
+
+ /*
+ * Upgrade with encryption...
+ */
+
+ httpEncryption(cups_server, HTTP_ENCRYPT_REQUIRED);
+
+ /*
+ * Try again, this time with encryption enabled...
+ */
+
+ continue;
+ }
+#endif /* HAVE_LIBSSL */
+ }
+ while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
+
+ /*
+ * See if we actually got the file or an error...
+ */
+
+ if (status != HTTP_OK)
+ {
+ close(fd);
+ unlink(filename);
+ httpFlush(cups_server);
+ httpClose(cups_server);
+ cups_server = NULL;
+ return (NULL);
+ }
+
+ /*
+ * OK, we need to copy the file...
+ */
+
+ while ((bytes =
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ httpRead
+#else
+ httpRead2
+#endif
+ (cups_server, buffer, sizeof(buffer))) > 0)
+ {
+ write(fd, buffer, bytes);
+ }
+
+ close(fd);
+
+ return (filename);
+}
+
+int /* O - Status of operation */
+cupsPutConf(const char *name) /* I - Name of the config file to send */
+{
+ int fd; /* PPD file */
+ int bytes; /* Number of bytes read */
+ char buffer[8192]; /* Buffer for file */
+ char resource[HTTP_MAX_URI]; /* Resource name */
+ const char *password; /* Password string */
+ char realm[HTTP_MAX_VALUE], /* realm="xyz" string */
+ nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */
+ plain[255], /* Plaintext username:password */
+ encode[512]; /* Encoded username:password */
+ http_status_t status; /* HTTP status from server */
+ char prompt[1024]; /* Prompt string */
+ int digest_tries; /* Number of tries with Digest */
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ const char *fqdn = 0;
+#else
+ char fqdn[ HTTP_MAX_URI ]; /* Server name buffer */
+#endif
+
+ if (name == NULL)
+ return 0;
+
+ /*
+ * Connect to the correct server as needed...
+ */
+
+ if ((cups_server = httpConnectEncrypt(cupsServer(), ippPort(),
+ cupsEncryption())) == NULL)
+ {
+ last_error = IPP_SERVICE_UNAVAILABLE;
+ return 0;
+ }
+
+ /*
+ * Open the local config file...
+ */
+
+ if ((fd = open(name, O_RDONLY)) < 0)
+ {
+ /*
+ * Can't open file; close the server connection and return NULL...
+ */
+
+ httpFlush(cups_server);
+ httpClose(cups_server);
+ cups_server = NULL;
+ return 0;
+ }
+
+ /*
+ * And send a request to the HTTP server...
+ */
+
+ strncpy(resource, "/admin/conf/cupsd.conf", sizeof(resource));
+
+ digest_tries = 0;
+
+ do
+ {
+ httpClearFields(cups_server);
+ httpSetField(cups_server, HTTP_FIELD_HOST, cupsServer());
+ httpSetField(cups_server, HTTP_FIELD_AUTHORIZATION, authstring);
+ httpSetField(cups_server, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
+
+ if (httpPut(cups_server, resource))
+ {
+ if (httpReconnect(cups_server))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+ else
+ {
+ status = HTTP_UNAUTHORIZED;
+ continue;
+ }
+ }
+
+ /* send the file now */
+ lseek(fd, 0, SEEK_SET);
+ status = HTTP_CONTINUE;
+ while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ if (httpCheck(cups_server))
+ {
+ if ((status = httpUpdate(cups_server)) != HTTP_CONTINUE)
+ break;
+ }
+ else
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ httpWrite
+#else
+ httpWrite2
+#endif
+ (cups_server, buffer, bytes);
+
+ if (status == HTTP_CONTINUE)
+ {
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ httpWrite
+#else
+ httpWrite2
+#endif
+ (cups_server, buffer, 0);
+ while ((status = httpUpdate(cups_server)) == HTTP_CONTINUE);
+ }
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ const char *www_authenticate;
+ fprintf(stderr,"cupsPutConf: unauthorized...");
+
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(cups_server);
+
+ /*
+ * See if we can do local authentication...
+ */
+
+ if (cups_local_auth(cups_server))
+ continue;
+
+ /*
+ * See if we should retry the current digest password...
+ */
+
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ www_authenticate = cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE];
+#else
+ www_authenticate = httpGetField( cups_server, HTTP_FIELD_WWW_AUTHENTICATE );
+#endif
+ if (strncmp(www_authenticate, "Basic", 5) == 0 ||
+ digest_tries > 1 || !pwdstring[0])
+ {
+ /*
+ * Nope - get a password from the user...
+ */
+
+
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ fqdn = cups_server->hostname;
+#else
+ httpGetHostname( cups_server, fqdn, sizeof( fqdn ) );
+#endif
+ snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(), fqdn );
+
+ if ((password = cupsGetPassword(prompt)) == NULL)
+ break;
+ if (!password[0])
+ break;
+
+ strncpy(pwdstring, password, sizeof(pwdstring) - 1);
+ pwdstring[sizeof(pwdstring) - 1] = '\0';
+
+ digest_tries = 0;
+ }
+ else
+ digest_tries ++;
+
+ /*
+ * Got a password; encode it for the server...
+ */
+
+#if CUPS_VERSION_MAJOR - 0 <= 1 && CUPS_VERSION_MINOR - 0 < 2
+ www_authenticate = cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE];
+#else
+ www_authenticate = httpGetField( cups_server, HTTP_FIELD_WWW_AUTHENTICATE );
+#endif
+ if (strncmp(www_authenticate, "Basic", 5) == 0)
+ {
+ /*
+ * Basic authentication...
+ */
+
+ snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), pwdstring);
+#if CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2
+ httpEncode64_2(encode, sizeof(encode), plain, sizeof(plain));
+#else
+ httpEncode64(encode, plain);
+#endif
+ snprintf(authstring, sizeof(authstring), "Basic %s", encode);
+ }
+ else
+ {
+ /*
+ * Digest authentication...
+ */
+
+ httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
+ httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
+
+ httpMD5(cupsUser(), realm, pwdstring, encode);
+ httpMD5Final(nonce, "GET", resource, encode);
+ snprintf(authstring, sizeof(authstring),
+ "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
+ "response=\"%s\"", cupsUser(), realm, nonce, encode);
+ }
+
+ continue;
+ }
+#ifdef HAVE_LIBSSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(cups_server);
+
+ /*
+ * Upgrade with encryption...
+ */
+
+ httpEncryption(cups_server, HTTP_ENCRYPT_REQUIRED);
+
+ /*
+ * Try again, this time with encryption enabled...
+ */
+
+ continue;
+ }
+#endif /* HAVE_LIBSSL */
+ }
+ while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
+
+ /*
+ * See if we actually got the file or an error...
+ */
+
+ if (status != HTTP_CREATED)
+ {
+ httpFlush(cups_server);
+ httpClose(cups_server);
+ cups_server = NULL;
+ close(fd);
+ return 0;
+ }
+
+ close(fd);
+
+ return 1;
+}
+
+static int /* O - 1 if available, 0 if not */
+cups_local_auth(http_t *http) /* I - Connection */
+{
+ int pid; /* Current process ID */
+ FILE *fp; /* Certificate file */
+ char filename[1024], /* Certificate filename */
+ certificate[33];/* Certificate string */
+ const char *root; /* Server root directory */
+
+
+ /*
+ * See if we are accessing localhost...
+ the struct has changed in newer versions - PiggZ (adam@piggz.co.uk)
+ */
+#if CUPS_VERSION_MAJOR == 1 && CUPS_VERSION_MINOR >= 2
+ if (!httpAddrLocalhost(http))
+#else
+ if (ntohl(*(int*)&http->hostaddr.sin_addr) != 0x7f000001 &&
+ strcasecmp(http->hostname, "localhost") != 0)
+#endif
+ return (0);
+
+ /*
+ * Try opening a certificate file for this PID. If that fails,
+ * try the root certificate...
+ */
+
+ if ((root = getenv("CUPS_SERVERROOT")) == NULL)
+ root = CUPS_SERVERROOT;
+
+ pid = getpid();
+ snprintf(filename, sizeof(filename), "%s/certs/%d", root, pid);
+ if ((fp = fopen(filename, "r")) == NULL && pid > 0)
+ {
+ snprintf(filename, sizeof(filename), "%s/certs/0", root);
+ fp = fopen(filename, "r");
+ }
+
+ if (fp == NULL)
+ return (0);
+
+ /*
+ * Read the certificate from the file...
+ */
+
+ fgets(certificate, sizeof(certificate), fp);
+ fclose(fp);
+
+ /*
+ * Set the authorization string and return...
+ */
+
+ snprintf(authstring, sizeof(authstring), "Local %s", certificate);
+
+ return (1);
+}
+