From 0e5503165504aa434cffce05d96d4241beb9452f Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@7a7537e8-13f0-0310-91df-b6672ffda945> Date: Sun, 31 Aug 2003 11:25:35 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'branch-1.2'. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/branches/branch-1.2@3895 7a7537e8-13f0-0310-91df-b6672ffda945 --- cups/auth.c | 238 +++++++++++++++++++++++++ cups/getputfile.c | 435 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 673 insertions(+) create mode 100644 cups/auth.c create mode 100644 cups/getputfile.c diff --git a/cups/auth.c b/cups/auth.c new file mode 100644 index 0000000000..e41ba945f9 --- /dev/null +++ b/cups/auth.c @@ -0,0 +1,238 @@ +/* + * "$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 +#include +#include +#include +#include +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#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 $". + */ diff --git a/cups/getputfile.c b/cups/getputfile.c new file mode 100644 index 0000000000..bb38244cb2 --- /dev/null +++ b/cups/getputfile.c @@ -0,0 +1,435 @@ +/* + * "$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 +#include +#include +#include +#include +#if defined(WIN32) || defined(__EMX__) +# include +#else +# include +#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 $". + */ -- 2.47.2