]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/auth.c
Merge changes from CUPS 1.4svn-r8659
[thirdparty/cups.git] / cups / auth.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: auth.c 7720 2008-07-11 22:46:21Z mike $"
ef416fc2 3 *
4 * Authentication functions for the Common UNIX Printing System (CUPS).
5 *
e07d4801 6 * Copyright 2007-2009 by Apple Inc.
b86bc4cf 7 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 8 *
f7deaa1a 9 * This file contains Kerberos support code, copyright 2006 by
10 * Jelmer Vernooij.
11 *
ef416fc2 12 * These coded instructions, statements, and computer programs are the
bc44d920 13 * property of Apple Inc. and are protected by Federal copyright
14 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
15 * which should have been included with this file. If this file is
16 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 17 *
18 * This file is subject to the Apple OS-Developed Software exception.
19 *
20 * Contents:
21 *
22 * cupsDoAuthentication() - Authenticate a request.
e07d4801
MS
23 * cups_get_gssname() - Get GSSAPI name for authentication.
24 * cups_gss_printf() - Show error messages from GSSAPI...
ef416fc2 25 * cups_local_auth() - Get the local authorization certificate if
26 * available/applicable...
27 */
28
29/*
30 * Include necessary headers...
31 */
32
33#include "globals.h"
34#include "debug.h"
35#include <stdlib.h>
36#include <ctype.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <sys/stat.h>
40#if defined(WIN32) || defined(__EMX__)
41# include <io.h>
42#else
43# include <unistd.h>
44#endif /* WIN32 || __EMX__ */
45
f7deaa1a 46#if HAVE_AUTHORIZATION_H
47# include <Security/Authorization.h>
48# ifdef HAVE_SECBASEPRIV_H
49# include <Security/SecBasePriv.h>
50# else
51extern const char *cssmErrorString(int error);
52# endif /* HAVE_SECBASEPRIV_H */
53#endif /* HAVE_AUTHORIZATION_H */
54
bc44d920 55#if defined(SO_PEERCRED) && defined(AF_LOCAL)
56# include <pwd.h>
57#endif /* SO_PEERCRED && AF_LOCAL */
58
ef416fc2 59
60/*
61 * Local functions...
62 */
63
f7deaa1a 64#ifdef HAVE_GSSAPI
e07d4801 65static gss_name_t cups_get_gssname(http_t *http, const char *service_name);
f7deaa1a 66# ifdef DEBUG
e07d4801
MS
67static void cups_gss_printf(OM_uint32 major_status, OM_uint32 minor_status,
68 const char *message);
355e94dc 69# else
e07d4801
MS
70# define cups_gss_printf(major, minor, message)
71# endif /* DEBUG */
f7deaa1a 72#endif /* HAVE_GSSAPI */
ef416fc2 73static int cups_local_auth(http_t *http);
74
75
76/*
77 * 'cupsDoAuthentication()' - Authenticate a request.
78 *
5a738aea 79 * This function should be called in response to a @code HTTP_UNAUTHORIZED@
ef416fc2 80 * status, prior to resubmitting your request.
81 *
426c6a59 82 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 83 */
84
85int /* O - 0 on success, -1 on error */
f11a948a
MS
86cupsDoAuthentication(
87 http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
88 const char *method, /* I - Request method ("GET", "POST", "PUT") */
89 const char *resource) /* I - Resource path */
ef416fc2 90{
91 const char *password; /* Password string */
92 char prompt[1024], /* Prompt for user */
93 realm[HTTP_MAX_VALUE], /* realm="xyz" string */
5a738aea 94 nonce[HTTP_MAX_VALUE]; /* nonce="xyz" string */
f7deaa1a 95 int localauth; /* Local authentication result */
b86bc4cf 96 _cups_globals_t *cg; /* Global data */
ef416fc2 97
98
e07d4801 99 DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")",
ef416fc2 100 http, method, resource));
e07d4801 101 DEBUG_printf(("2cupsDoAuthentication: digest_tries=%d, userpass=\"%s\"",
ef416fc2 102 http->digest_tries, http->userpass));
e07d4801 103 DEBUG_printf(("2cupsDoAuthentication: WWW-Authenticate=\"%s\"",
07725fee 104 httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE)));
ef416fc2 105
f11a948a
MS
106 if (!http)
107 http = _cupsConnect();
108
109 if (!http || !method || !resource)
110 return (-1);
111
ef416fc2 112 /*
113 * Clear the current authentication string...
114 */
115
355e94dc 116 httpSetAuthString(http, NULL, NULL);
ef416fc2 117
118 /*
119 * See if we can do local authentication...
120 */
121
f7deaa1a 122 if (http->digest_tries < 3)
ef416fc2 123 {
f7deaa1a 124 if ((localauth = cups_local_auth(http)) == 0)
125 {
e07d4801 126 DEBUG_printf(("2cupsDoAuthentication: authstring=\"%s\"",
f7deaa1a 127 http->authstring));
128
129 if (http->status == HTTP_UNAUTHORIZED)
130 http->digest_tries ++;
131
132 return (0);
133 }
134 else if (localauth == -1)
f11a948a
MS
135 {
136 http->status = HTTP_AUTHORIZATION_CANCELED;
f7deaa1a 137 return (-1); /* Error or canceled */
f11a948a 138 }
ef416fc2 139 }
140
141 /*
142 * Nope, see if we should retry the current username:password...
143 */
144
f7deaa1a 145 if ((http->digest_tries > 1 || !http->userpass[0]) &&
146 strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
ef416fc2 147 {
148 /*
149 * Nope - get a new password from the user...
150 */
151
b86bc4cf 152 cg = _cupsGlobals();
153
154 if (!cg->lang_default)
155 cg->lang_default = cupsLangDefault();
156
157 snprintf(prompt, sizeof(prompt),
158 _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
159 cupsUser(),
160 http->hostname[0] == '/' ? "localhost" : http->hostname);
ef416fc2 161
162 http->digest_tries = strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE],
163 "Digest", 5) != 0;
164 http->userpass[0] = '\0';
165
f11a948a
MS
166 if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
167 {
168 http->status = HTTP_AUTHORIZATION_CANCELED;
ef416fc2 169 return (-1);
f11a948a 170 }
ef416fc2 171
172 if (!password[0])
f11a948a
MS
173 {
174 http->status = HTTP_AUTHORIZATION_CANCELED;
ef416fc2 175 return (-1);
f11a948a 176 }
ef416fc2 177
178 snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(),
179 password);
180 }
181 else if (http->status == HTTP_UNAUTHORIZED)
182 http->digest_tries ++;
183
184 /*
185 * Got a password; encode it for the server...
186 */
187
f7deaa1a 188 if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
189 {
190#ifdef HAVE_GSSAPI
191 /*
192 * Kerberos authentication...
193 */
194
195 OM_uint32 minor_status, /* Minor status code */
196 major_status; /* Major status code */
197 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER,
198 /* Output token */
199 input_token = GSS_C_EMPTY_BUFFER;
200 /* Input token */
201 char *gss_service_name;
202 /* GSS service name */
355e94dc 203# ifdef USE_SPNEGO
f7deaa1a 204 const char *authorization;
205 /* Pointer into Authorization string */
355e94dc 206# endif /* USE_SPNEGO */
f7deaa1a 207
208
f42414bf 209# ifdef __APPLE__
210 /*
211 * If the weak-linked GSSAPI/Kerberos library is not present, don't try
212 * to use it...
213 */
214
215 if (gss_init_sec_context == NULL)
216 {
e07d4801 217 DEBUG_puts("1cupsDoAuthentication: Weak-linked GSSAPI/Kerberos framework "
f42414bf 218 "is not present");
f11a948a
MS
219 http->status = HTTP_AUTHORIZATION_CANCELED;
220
f42414bf 221 return (-1);
222 }
223# endif /* __APPLE__ */
224
355e94dc
MS
225 if (http->status == HTTP_UNAUTHORIZED && http->digest_tries >= 3)
226 {
e07d4801 227 DEBUG_printf(("1cupsDoAuthentication: too many Negotiate tries (%d)",
355e94dc 228 http->digest_tries));
f11a948a 229 http->status = HTTP_AUTHORIZATION_CANCELED;
355e94dc
MS
230
231 return (-1);
232 }
233
f7deaa1a 234 if (http->gssname == GSS_C_NO_NAME)
235 {
236 if ((gss_service_name = getenv("CUPS_GSSSERVICENAME")) == NULL)
237 gss_service_name = CUPS_DEFAULT_GSSSERVICENAME;
238 else
e07d4801
MS
239 DEBUG_puts("2cupsDoAuthentication: GSS service name set via "
240 "environment variable");
f7deaa1a 241
e07d4801 242 http->gssname = cups_get_gssname(http, gss_service_name);
f7deaa1a 243 }
244
355e94dc 245# ifdef USE_SPNEGO /* We don't implement SPNEGO just yet... */
f7deaa1a 246 /*
247 * Find the start of the Kerberos input token...
248 */
249
250 authorization = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
251
252 authorization += 9;
253 while (*authorization && isspace(*authorization & 255))
254 authorization ++;
255
256 if (*authorization)
257 {
258 /*
355e94dc 259 * Decode the authorization string to get the input token...
f7deaa1a 260 */
355e94dc
MS
261
262 int len = strlen(authorization);
263
264 input_token.value = malloc(len);
265 input_token.value = httpDecode64_2(input_token.value, &len,
266 authorization);
267 input_token.length = len;
268
269# ifdef DEBUG
270 {
271 char *ptr = (char *)input_token.value;
272 int left = len;
273
274 fputs("input_token=", stdout);
275 while (left > 0)
276 {
277 if (*ptr < ' ')
278 printf("\\%03o", *ptr & 255);
279 else
280 putchar(*ptr);
281 ptr ++;
282 left --;
283 }
284 putchar('\n');
285 }
286# endif /* DEBUG */
f7deaa1a 287 }
355e94dc 288# endif /* USE_SPNEGO */
bc44d920 289
290 if (http->gssctx != GSS_C_NO_CONTEXT)
f7deaa1a 291 {
1f0275e3 292 gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
bc44d920 293 http->gssctx = GSS_C_NO_CONTEXT;
f7deaa1a 294 }
295
296 major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
297 &http->gssctx,
298 http->gssname, http->gssmech,
e07d4801
MS
299#ifdef GSS_C_DELEG_POLICY_FLAG
300 GSS_C_DELEG_POLICY_FLAG |
301#endif /* GSS_C_DELEG_POLICY_FLAG */
302 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
bc44d920 303 GSS_C_INDEFINITE,
f7deaa1a 304 GSS_C_NO_CHANNEL_BINDINGS,
305 &input_token, &http->gssmech,
306 &output_token, NULL, NULL);
307
308 if (input_token.value)
309 free(input_token.value);
310
311 if (GSS_ERROR(major_status))
312 {
e07d4801
MS
313 cups_gss_printf(major_status, minor_status,
314 "cupsDoAuthentication: Unable to initialize security "
315 "context");
f11a948a
MS
316 http->status = HTTP_AUTHORIZATION_CANCELED;
317
f7deaa1a 318 return (-1);
319 }
320
f7deaa1a 321 if (major_status == GSS_S_CONTINUE_NEEDED)
e07d4801
MS
322 cups_gss_printf(major_status, minor_status,
323 "cupsDoAuthentication: Continuation needed!");
f7deaa1a 324
5a738aea 325 if (output_token.length > 0 && output_token.length <= 65536)
f7deaa1a 326 {
5a738aea
MS
327 /*
328 * Allocate the authorization string since Windows KDCs can have
329 * arbitrarily large credentials...
330 */
331
332 int authsize = 10 + /* "Negotiate " */
333 output_token.length * 4 / 3 + 1 + /* Base64 */
334 1; /* nul */
335
336 httpSetAuthString(http, NULL, NULL);
337
338 if ((http->authstring = malloc(authsize)) == NULL)
339 {
340 http->authstring = http->_authstring;
341 authsize = sizeof(http->_authstring);
342 }
343
344 strcpy(http->authstring, "Negotiate ");
345 httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value,
f7deaa1a 346 output_token.length);
f7deaa1a 347
1f0275e3 348 gss_release_buffer(&minor_status, &output_token);
f7deaa1a 349 }
5a738aea
MS
350 else
351 {
e07d4801
MS
352 DEBUG_printf(("1cupsDoAuthentication: Kerberos credentials too large - "
353 "%d bytes!", (int)output_token.length));
f11a948a 354 http->status = HTTP_AUTHORIZATION_CANCELED;
1f0275e3 355 gss_release_buffer(&minor_status, &output_token);
5a738aea
MS
356
357 return (-1);
358 }
f7deaa1a 359#endif /* HAVE_GSSAPI */
360 }
361 else if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6))
ef416fc2 362 {
363 /*
364 * Basic authentication...
365 */
366
5a738aea
MS
367 char encode[256]; /* Base64 buffer */
368
369
ef416fc2 370 httpEncode64_2(encode, sizeof(encode), http->userpass,
b86bc4cf 371 (int)strlen(http->userpass));
355e94dc 372 httpSetAuthString(http, "Basic", encode);
ef416fc2 373 }
374 else
375 {
376 /*
377 * Digest authentication...
378 */
379
5a738aea
MS
380 char encode[33], /* MD5 buffer */
381 digest[1024]; /* Digest auth data */
355e94dc
MS
382
383
ef416fc2 384 httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
385 httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
386
387 httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode);
388 httpMD5Final(nonce, method, resource, encode);
355e94dc
MS
389 snprintf(digest, sizeof(digest),
390 "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", "
391 "response=\"%s\"", cupsUser(), realm, nonce, resource, encode);
392 httpSetAuthString(http, "Digest", digest);
ef416fc2 393 }
394
e07d4801 395 DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring));
ef416fc2 396
397 return (0);
398}
399
400
f7deaa1a 401#ifdef HAVE_GSSAPI
f7deaa1a 402/*
e07d4801 403 * 'cups_get_gssname()' - Get CUPS service credentials for authentication.
f7deaa1a 404 */
405
406static gss_name_t /* O - Server name */
e07d4801 407cups_get_gssname(
f7deaa1a 408 http_t *http, /* I - Connection to server */
409 const char *service_name) /* I - Service name */
410{
411 gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
412 /* Service token */
bc44d920 413 OM_uint32 major_status, /* Major status code */
414 minor_status; /* Minor status code */
415 gss_name_t server_name; /* Server name */
416 char buf[1024], /* Name buffer */
417 fqdn[HTTP_MAX_URI]; /* Server name buffer */
418
419
e07d4801
MS
420 DEBUG_printf(("7cups_get_gssname(http=%p, service_name=\"%s\")", http,
421 service_name));
422
423
bc44d920 424 /*
425 * Get the hostname...
426 */
f7deaa1a 427
bc44d920 428 httpGetHostname(http, fqdn, sizeof(fqdn));
429
430 if (!strcmp(fqdn, "localhost"))
431 httpGetHostname(NULL, fqdn, sizeof(fqdn));
f7deaa1a 432
433 /*
434 * Get a server name we can use for authentication purposes...
435 */
436
bc44d920 437 snprintf(buf, sizeof(buf), "%s@%s", service_name, fqdn);
f7deaa1a 438
e07d4801 439 DEBUG_printf(("9cups_get_gssname: Looking up %s...", buf));
7ff4fea9 440
f7deaa1a 441 token.value = buf;
442 token.length = strlen(buf);
443 server_name = GSS_C_NO_NAME;
444 major_status = gss_import_name(&minor_status, &token,
445 GSS_C_NT_HOSTBASED_SERVICE,
446 &server_name);
447
448 if (GSS_ERROR(major_status))
449 {
e07d4801
MS
450 cups_gss_printf(major_status, minor_status,
451 "cups_get_gssname: gss_import_name() failed");
f7deaa1a 452 return (NULL);
453 }
454
455 return (server_name);
456}
e07d4801
MS
457
458
459# ifdef DEBUG
460/*
461 * 'cups_gss_printf()' - Show debug error messages from GSSAPI...
462 */
463
464static void
465cups_gss_printf(OM_uint32 major_status,/* I - Major status code */
466 OM_uint32 minor_status,/* I - Minor status code */
467 const char *message) /* I - Prefix for error message */
468{
469 OM_uint32 err_major_status, /* Major status code for display */
470 err_minor_status; /* Minor status code for display */
471 OM_uint32 msg_ctx; /* Message context */
472 gss_buffer_desc major_status_string = GSS_C_EMPTY_BUFFER,
473 /* Major status message */
474 minor_status_string = GSS_C_EMPTY_BUFFER;
475 /* Minor status message */
476
477
478 msg_ctx = 0;
479 err_major_status = gss_display_status(&err_minor_status,
480 major_status,
481 GSS_C_GSS_CODE,
482 GSS_C_NO_OID,
483 &msg_ctx,
484 &major_status_string);
485
486 if (!GSS_ERROR(err_major_status))
487 gss_display_status(&err_minor_status, minor_status, GSS_C_MECH_CODE,
488 GSS_C_NULL_OID, &msg_ctx, &minor_status_string);
489
68b10830 490 DEBUG_printf(("1%s: %s, %s", message, (char *)major_status_string.value,
e07d4801
MS
491 (char *)minor_status_string.value));
492
493 gss_release_buffer(&err_minor_status, &major_status_string);
494 gss_release_buffer(&err_minor_status, &minor_status_string);
495}
496# endif /* DEBUG */
f7deaa1a 497#endif /* HAVE_GSSAPI */
498
499
ef416fc2 500/*
501 * 'cups_local_auth()' - Get the local authorization certificate if
502 * available/applicable...
503 */
504
f7deaa1a 505static int /* O - 0 if available */
bc44d920 506 /* 1 if not available */
f7deaa1a 507 /* -1 error */
ef416fc2 508cups_local_auth(http_t *http) /* I - HTTP connection to server */
509{
510#if defined(WIN32) || defined(__EMX__)
511 /*
512 * Currently WIN32 and OS-2 do not support the CUPS server...
513 */
514
bc44d920 515 return (1);
ef416fc2 516#else
f7deaa1a 517 int pid; /* Current process ID */
518 FILE *fp; /* Certificate file */
e07d4801
MS
519 char trc[16], /* Try Root Certificate parameter */
520 filename[1024], /* Certificate filename */
f7deaa1a 521 certificate[33];/* Certificate string */
ef416fc2 522 _cups_globals_t *cg = _cupsGlobals(); /* Global data */
bc44d920 523# if defined(HAVE_AUTHORIZATION_H)
f7deaa1a 524 OSStatus status; /* Status */
525 AuthorizationItem auth_right; /* Authorization right */
526 AuthorizationRights auth_rights; /* Authorization rights */
527 AuthorizationFlags auth_flags; /* Authorization flags */
528 AuthorizationExternalForm auth_extrn; /* Authorization ref external */
529 char auth_key[1024]; /* Buffer */
530 char buffer[1024]; /* Buffer */
bc44d920 531# endif /* HAVE_AUTHORIZATION_H */
ef416fc2 532
533
e07d4801 534 DEBUG_printf(("7cups_local_auth(http=%p) hostaddr=%s, hostname=\"%s\"",
ef416fc2 535 http, httpAddrString(http->hostaddr, filename, sizeof(filename)), http->hostname));
536
537 /*
538 * See if we are accessing localhost...
539 */
540
541 if (!httpAddrLocalhost(http->hostaddr) &&
542 strcasecmp(http->hostname, "localhost") != 0)
543 {
e07d4801 544 DEBUG_puts("8cups_local_auth: Not a local connection!");
bc44d920 545 return (1);
ef416fc2 546 }
547
bc44d920 548# if defined(HAVE_AUTHORIZATION_H)
f7deaa1a 549 /*
550 * Delete any previous authorization reference...
551 */
552
b94498cf 553 if (http->auth_ref)
f7deaa1a 554 {
b94498cf 555 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
556 http->auth_ref = NULL;
f7deaa1a 557 }
558
e4572d57
MS
559 if (!getenv("GATEWAY_INTERFACE") &&
560 httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
f7deaa1a 561 auth_key, sizeof(auth_key)))
562 {
563 status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
b94498cf 564 kAuthorizationFlagDefaults, &http->auth_ref);
f7deaa1a 565 if (status != errAuthorizationSuccess)
566 {
e07d4801 567 DEBUG_printf(("8cups_local_auth: AuthorizationCreate() returned %d (%s)",
f7deaa1a 568 (int)status, cssmErrorString(status)));
569 return (-1);
570 }
571
572 auth_right.name = auth_key;
573 auth_right.valueLength = 0;
574 auth_right.value = NULL;
575 auth_right.flags = 0;
576
577 auth_rights.count = 1;
578 auth_rights.items = &auth_right;
579
580 auth_flags = kAuthorizationFlagDefaults |
581 kAuthorizationFlagPreAuthorize |
582 kAuthorizationFlagInteractionAllowed |
583 kAuthorizationFlagExtendRights;
584
b94498cf 585 status = AuthorizationCopyRights(http->auth_ref, &auth_rights,
f7deaa1a 586 kAuthorizationEmptyEnvironment,
587 auth_flags, NULL);
588 if (status == errAuthorizationSuccess)
b94498cf 589 status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn);
f7deaa1a 590
591 if (status == errAuthorizationSuccess)
592 {
593 /*
594 * Set the authorization string and return...
595 */
596
597 httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn,
598 sizeof(auth_extrn));
599
355e94dc 600 httpSetAuthString(http, "AuthRef", buffer);
f7deaa1a 601
e07d4801 602 DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
f7deaa1a 603 http->authstring));
604 return (0);
605 }
606 else if (status == errAuthorizationCanceled)
607 return (-1);
608
e07d4801 609 DEBUG_printf(("9cups_local_auth: AuthorizationCopyRights() returned %d (%s)",
f7deaa1a 610 (int)status, cssmErrorString(status)));
611
612 /*
613 * Fall through to try certificates...
614 */
615 }
bc44d920 616# endif /* HAVE_AUTHORIZATION_H */
f7deaa1a 617
f11a948a
MS
618# if defined(SO_PEERCRED) && defined(AF_LOCAL)
619 /*
620 * See if we can authenticate using the peer credentials provided over a
621 * domain socket; if so, specify "PeerCred username" as the authentication
622 * information...
623 */
624
68b10830
MS
625# ifdef HAVE_GSSAPI
626 if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) &&
627# else
628 if (
629# endif /* HAVE_GSSAPI */
630 http->hostaddr->addr.sa_family == AF_LOCAL &&
f11a948a
MS
631 !getenv("GATEWAY_INTERFACE")) /* Not via CGI programs... */
632 {
633 /*
634 * Verify that the current cupsUser() matches the current UID...
635 */
636
637 struct passwd *pwd; /* Password information */
638 const char *username; /* Current username */
639
640 username = cupsUser();
641
642 if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid())
643 {
644 httpSetAuthString(http, "PeerCred", username);
645
646 DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
647 http->authstring));
648
649 return (0);
650 }
651 }
652# endif /* SO_PEERCRED && AF_LOCAL */
653
ef416fc2 654 /*
655 * Try opening a certificate file for this PID. If that fails,
656 * try the root certificate...
657 */
658
659 pid = getpid();
660 snprintf(filename, sizeof(filename), "%s/certs/%d", cg->cups_statedir, pid);
661 if ((fp = fopen(filename, "r")) == NULL && pid > 0)
662 {
bc44d920 663 /*
e07d4801 664 * No certificate for this PID; see if we can get the root certificate...
bc44d920 665 */
666
e07d4801
MS
667 DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s",
668 filename, strerror(errno)));
669
670#ifdef HAVE_GSSAPI
355e94dc 671 if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
bc44d920 672 {
673 /*
e07d4801 674 * Kerberos required, don't try the root certificate...
bc44d920 675 */
676
677 return (1);
678 }
679#endif /* HAVE_GSSAPI */
680
e07d4801
MS
681 if (!httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "trc", trc,
682 sizeof(trc)))
683 {
684 /*
685 * Scheduler doesn't want us to use the root certificate...
686 */
687
688 return (1);
689 }
690
ef416fc2 691 snprintf(filename, sizeof(filename), "%s/certs/0", cg->cups_statedir);
692 fp = fopen(filename, "r");
693 }
694
f7deaa1a 695 if (fp)
ef416fc2 696 {
f7deaa1a 697 /*
698 * Read the certificate from the file...
699 */
ef416fc2 700
f7deaa1a 701 fgets(certificate, sizeof(certificate), fp);
702 fclose(fp);
ef416fc2 703
f7deaa1a 704 /*
705 * Set the authorization string and return...
706 */
ef416fc2 707
355e94dc 708 httpSetAuthString(http, "Local", certificate);
ef416fc2 709
e07d4801 710 DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
f7deaa1a 711 http->authstring));
ef416fc2 712
f7deaa1a 713 return (0);
714 }
715
716 return (1);
ef416fc2 717#endif /* WIN32 || __EMX__ */
718}
719
720
721/*
b19ccc9e 722 * End of "$Id: auth.c 7720 2008-07-11 22:46:21Z mike $".
ef416fc2 723 */