--- /dev/null
+/*
+ * "$Id: auth.c,v 1.1 2003/08/29 21:26:40 mike Exp $"
+ *
+ * Authentication functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsDoAuthentication() - Authenticate a request...
+ * cups_local_auth() - Get the local authorization certificate if
+ * available/applicable...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "ipp.h"
+#include "language.h"
+#include "string.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * Local functions...
+ */
+
+static int cups_local_auth(http_t *http);
+
+
+/*
+ * 'cupsDoAuthentication()' - Authenticate a request...
+ */
+
+int /* O - 0 on success, -1 on error */
+cupsDoAuthentication(http_t *http, /* I - HTTP connection to server */
+ const char *method,/* I - Request method (GET, POST, PUT) */
+ const char *resource)
+ /* I - Resource path */
+{
+ const char *password; /* Password string */
+ char prompt[1024], /* Prompt for user */
+ realm[HTTP_MAX_VALUE], /* realm="xyz" string */
+ nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */
+ encode[512]; /* Encoded username:password */
+
+
+ /*
+ * Clear the current authentication string...
+ */
+
+ http->authstring[0] = '\0';
+
+ /*
+ * See if we can do local authentication...
+ */
+
+ if (!cups_local_auth(http))
+ return (0);
+
+ /*
+ * Nope, see if we should retry the current digest password...
+ */
+
+ if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0 ||
+ http->digest_tries > 1 || !http->userpass[0])
+ {
+ /*
+ * Nope - get a new password from the user...
+ */
+
+ snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(),
+ http->hostname);
+
+ http->digest_tries = 0;
+ http->userpass[0] = '\0';
+
+ if ((password = cupsGetPassword(prompt)) == NULL)
+ return (-1);
+
+ if (!password[0])
+ return (-1);
+
+ snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(),
+ password);
+ }
+ else
+ http->digest_tries ++;
+
+ /*
+ * Got a password; encode it for the server...
+ */
+
+ if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0)
+ {
+ /*
+ * Basic authentication...
+ */
+
+ httpEncode64(encode, http->userpass);
+ snprintf(http->authstring, sizeof(http->authstring), "Basic %s", encode);
+ }
+ else
+ {
+ /*
+ * Digest authentication...
+ */
+
+ httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
+ httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
+
+ httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode);
+ httpMD5Final(nonce, "POST", resource, encode);
+ snprintf(http->authstring, sizeof(http->authstring),
+ "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
+ "response=\"%s\"", cupsUser(), realm, nonce, encode);
+ }
+
+ return (0);
+}
+
+
+/*
+ * 'cups_local_auth()' - Get the local authorization certificate if
+ * available/applicable...
+ */
+
+static int /* O - 0 if available, -1 if not */
+cups_local_auth(http_t *http) /* I - HTTP connection to server */
+{
+#if defined(WIN32) || defined(__EMX__)
+ /*
+ * Currently WIN32 and OS-2 do not support the CUPS server...
+ */
+
+ return (-1);
+#else
+ int pid; /* Current process ID */
+ FILE *fp; /* Certificate file */
+ char filename[1024], /* Certificate filename */
+ certificate[33]; /* Certificate string */
+ const char *root; /* Server root directory */
+
+
+ DEBUG_printf(("cups_local_auth(http=%p) hostaddr=%08x, hostname=\"%s\"\n",
+ http, ntohl(http->hostaddr.sin_addr.s_addr), http->hostname));
+
+ /*
+ * See if we are accessing localhost...
+ */
+
+ if (ntohl(http->hostaddr.sin_addr.s_addr) != 0x7f000001 &&
+ strcasecmp(http->hostname, "localhost") != 0)
+ {
+ DEBUG_puts("cups_local_auth: Not a local connection!");
+ return (-1);
+ }
+
+ /*
+ * 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)
+ {
+ DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n",
+ filename, strerror(errno)));
+
+ snprintf(filename, sizeof(filename), "%s/certs/0", root);
+ fp = fopen(filename, "r");
+ }
+
+ if (fp == NULL)
+ {
+ DEBUG_printf(("cups_local_auth: Unable to open file %s: %s\n",
+ filename, strerror(errno)));
+ return (-1);
+ }
+
+ /*
+ * Read the certificate from the file...
+ */
+
+ fgets(certificate, sizeof(certificate), fp);
+ fclose(fp);
+
+ /*
+ * Set the authorization string and return...
+ */
+
+ snprintf(http->authstring, sizeof(http->authstring), "Local %s", certificate);
+
+ DEBUG_printf(("cups_local_auth: Returning authstring = \"%s\"\n",
+ authstring));
+
+ return (0);
+#endif /* WIN32 || __EMX__ */
+}
+
+
+/*
+ * End of "$Id: auth.c,v 1.1 2003/08/29 21:26:40 mike Exp $".
+ */
--- /dev/null
+/*
+ * "$Id: getputfile.c,v 1.1 2003/08/29 21:26:41 mike Exp $"
+ *
+ * Get/put file functions for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2003 by Easy Software Products.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ *
+ * Contents:
+ *
+ * cupsGetFd() - Get a file from the server.
+ * cupsGetFile() - Get a file from the server.
+ * cupsPutFd() - Put a file on the server.
+ * cupsPutFile() - Put a file on the server.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups.h"
+#include "ipp.h"
+#include "language.h"
+#include "string.h"
+#include "debug.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#if defined(WIN32) || defined(__EMX__)
+# include <io.h>
+#else
+# include <unistd.h>
+#endif /* WIN32 || __EMX__ */
+
+
+/*
+ * 'cupsGetFd()' - Get a file from the server.
+ */
+
+http_status_t /* O - Status */
+cupsGetFd(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ int fd) /* I - File descriptor */
+{
+ int bytes; /* Number of bytes read */
+ char buffer[8192]; /* Buffer for file */
+ http_status_t status; /* HTTP status from server */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !resource || fd < 0)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Then send GET requests to the HTTP server...
+ */
+
+ do
+ {
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
+
+ if (httpGet(http, resource))
+ {
+ if (httpReconnect(http))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+ else
+ {
+ status = HTTP_UNAUTHORIZED;
+ continue;
+ }
+ }
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * See if we can do authentication...
+ */
+
+ if (cupsDoAuthentication(http, "GET", resource))
+ break;
+
+ httpReconnect(http);
+
+ continue;
+ }
+ else if (status == HTTP_ERROR)
+ {
+#ifdef WIN32
+ if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH)
+#else
+ if (http->error != ENETDOWN && http->error != ENETUNREACH)
+#endif /* WIN32 */
+ continue;
+ else
+ break;
+ }
+#ifdef HAVE_LIBSSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * Upgrade with encryption...
+ */
+
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+
+ /*
+ * Try again, this time with encryption enabled...
+ */
+
+ continue;
+ }
+#endif /* HAVE_LIBSSL */
+ }
+ while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
+ status == HTTP_ERROR);
+
+ /*
+ * See if we actually got the file or an error...
+ */
+
+ if (status == HTTP_OK)
+ {
+ /*
+ * Yes, copy the file...
+ */
+
+ while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
+ write(fd, buffer, bytes);
+ }
+ else
+ httpFlush(http);
+
+ /*
+ * Return the request status...
+ */
+
+ return (status);
+}
+
+
+/*
+ * 'cupsGetFile()' - Get a file from the server.
+ */
+
+http_status_t /* O - Status */
+cupsGetFile(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ const char *filename) /* I - Filename */
+{
+ int fd; /* File descriptor */
+ http_status_t status; /* Status */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !resource || !filename)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Create the file...
+ */
+
+ if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
+ {
+ /*
+ * Couldn't open the file!
+ */
+
+ http->error = errno;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Get the file...
+ */
+
+ status = cupsGetFd(http, resource, fd);
+
+ /*
+ * If the file couldn't be gotten, then remove the file...
+ */
+
+ close(fd);
+
+ if (status != HTTP_OK)
+ unlink(filename);
+
+ /*
+ * Return the HTTP status code...
+ */
+
+ return (status);
+}
+
+
+/*
+ * 'cupsPutFd()' - Put a file on the server.
+ */
+
+http_status_t /* O - Status */
+cupsPutFd(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ int fd) /* I - File descriptor */
+{
+ int bytes; /* Number of bytes read */
+ char buffer[8192]; /* Buffer for file */
+ http_status_t status; /* HTTP status from server */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !resource || fd < 0)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Then send PUT requests to the HTTP server...
+ */
+
+ do
+ {
+ httpClearFields(http);
+ httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
+ httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
+
+ if (httpPut(http, resource))
+ {
+ if (httpReconnect(http))
+ {
+ status = HTTP_ERROR;
+ break;
+ }
+ else
+ {
+ status = HTTP_UNAUTHORIZED;
+ continue;
+ }
+ }
+
+ /*
+ * Copy the file...
+ */
+
+ lseek(fd, 0, SEEK_SET);
+
+ status = HTTP_CONTINUE;
+
+ while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ if (httpCheck(http))
+ {
+ if ((status = httpUpdate(http)) != HTTP_CONTINUE)
+ break;
+ }
+ else
+ httpWrite(http, buffer, bytes);
+
+ if (status == HTTP_CONTINUE)
+ {
+ httpWrite(http, buffer, 0);
+
+ while ((status = httpUpdate(http)) == HTTP_CONTINUE);
+ }
+
+ if (status == HTTP_UNAUTHORIZED)
+ {
+ /*
+ * Flush any error message...
+ */
+
+ httpFlush(http);
+
+ /*
+ * See if we can do authentication...
+ */
+
+ if (cupsDoAuthentication(http, "PUT", resource))
+ break;
+
+ httpReconnect(http);
+
+ continue;
+ }
+ else if (status == HTTP_ERROR)
+ {
+#ifdef WIN32
+ if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH)
+#else
+ if (http->error != ENETDOWN && http->error != ENETUNREACH)
+#endif /* WIN32 */
+ continue;
+ else
+ break;
+ }
+#ifdef HAVE_LIBSSL
+ else if (status == HTTP_UPGRADE_REQUIRED)
+ {
+ /* Flush any error message... */
+ httpFlush(http);
+
+ /* Upgrade with encryption... */
+ httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+
+ /* Try again, this time with encryption enabled... */
+ continue;
+ }
+#endif /* HAVE_LIBSSL */
+ }
+ while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
+ status == HTTP_ERROR);
+
+ /*
+ * See if we actually put the file or an error...
+ */
+
+ if (status != HTTP_CREATED)
+ httpFlush(http);
+
+ return (status);
+}
+
+
+/*
+ * 'cupsPutFile()' - Put a file on the server.
+ */
+
+http_status_t /* O - Status */
+cupsPutFile(http_t *http, /* I - HTTP connection to server */
+ const char *resource, /* I - Resource name */
+ const char *filename) /* I - Filename */
+{
+ int fd; /* File descriptor */
+ http_status_t status; /* Status */
+
+
+ /*
+ * Range check input...
+ */
+
+ if (!http || !resource || !filename)
+ {
+ if (http)
+ http->error = EINVAL;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Open the local file...
+ */
+
+ if ((fd = open(filename, O_RDONLY)) < 0)
+ {
+ /*
+ * Couldn't open the file!
+ */
+
+ http->error = errno;
+
+ return (HTTP_ERROR);
+ }
+
+ /*
+ * Put the file...
+ */
+
+ status = cupsPutFd(http, resource, fd);
+
+ close(fd);
+
+ return (status);
+}
+
+
+/*
+ * End of "$Id: getputfile.c,v 1.1 2003/08/29 21:26:41 mike Exp $".
+ */