#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
static int cups_local_auth(http_t *http);
int
cupsDoAuthentication(http_t *http,
const char *method,
const char *resource)
{
const char *password;
char prompt[1024],
realm[HTTP_MAX_VALUE],
nonce[HTTP_MAX_VALUE],
encode[512];
DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")\n",
http, method, resource));
http->authstring[0] = '\0';
if (!cups_local_auth(http))
{
DEBUG_printf(("cupsDoAuthentication: authstring=\"%s\"\n", http->authstring));
return (0);
}
if (http->digest_tries > 1 || !http->userpass[0])
{
snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(),
http->hostname);
http->digest_tries = strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE],
"Basic", 5) == 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 if (http->status == HTTP_UNAUTHORIZED)
http->digest_tries ++;
if (strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0)
{
httpEncode64(encode, http->userpass);
snprintf(http->authstring, sizeof(http->authstring), "Basic %s", encode);
}
else
{
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, method, resource, encode);
snprintf(http->authstring, sizeof(http->authstring),
"Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
"uri=\"%s\", response=\"%s\"", cupsUser(), realm, nonce,
resource, encode);
}
DEBUG_printf(("cupsDoAuthentication: authstring=\"%s\"\n", http->authstring));
return (0);
}
static int
cups_local_auth(http_t *http)
{
#if defined(WIN32) || defined(__EMX__)
return (-1);
#else
int pid;
FILE *fp;
char filename[1024],
certificate[33];
const char *root;
DEBUG_printf(("cups_local_auth(http=%p) hostaddr=%08x, hostname=\"%s\"\n",
http, ntohl(http->hostaddr.sin_addr.s_addr), http->hostname));
if (ntohl(http->hostaddr.sin_addr.s_addr) != 0x7f000001 &&
strcasecmp(http->hostname, "localhost") != 0
#ifdef HAVE_DOMAINSOCKETS
&& http->hostaddr.sin_family != AF_LOCAL
#endif
)
{
DEBUG_puts("cups_local_auth: Not a local connection!");
return (-1);
}
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);
}
fgets(certificate, sizeof(certificate), fp);
fclose(fp);
snprintf(http->authstring, sizeof(http->authstring), "Local %s", certificate);
DEBUG_printf(("cups_local_auth: Returning authstring = \"%s\"\n",
http->authstring));
return (0);
#endif
}