1/* 2 * "$Id: auth.c 12131 2014-08-28 23:38:16Z msweet $" 3 * 4 * Authorization routines for the CUPS scheduler. 5 * 6 * Copyright 2007-2014 by Apple Inc. 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved. 8 * 9 * This file contains Kerberos support code, copyright 2006 by 10 * Jelmer Vernooij. 11 * 12 * These coded instructions, statements, and computer programs are the 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/". 17 */ 18 19/* 20 * Include necessary headers... 21 */ 22 23#include "cupsd.h" 24#include <grp.h> 25#ifdef HAVE_SHADOW_H 26# include <shadow.h> 27#endif /* HAVE_SHADOW_H */ 28#ifdef HAVE_CRYPT_H 29# include <crypt.h> 30#endif /* HAVE_CRYPT_H */ 31#if HAVE_LIBPAM 32# ifdef HAVE_PAM_PAM_APPL_H 33# include <pam/pam_appl.h> 34# else 35# include <security/pam_appl.h> 36# endif /* HAVE_PAM_PAM_APPL_H */ 37#endif /* HAVE_LIBPAM */ 38#ifdef HAVE_MEMBERSHIP_H 39# include <membership.h> 40#endif /* HAVE_MEMBERSHIP_H */ 41#ifdef HAVE_AUTHORIZATION_H 42# include <Security/AuthorizationTags.h> 43# ifdef HAVE_SECBASEPRIV_H 44# include <Security/SecBasePriv.h> 45# else 46extern const char *cssmErrorString(int error); 47# endif /* HAVE_SECBASEPRIV_H */ 48#endif /* HAVE_AUTHORIZATION_H */ 49#ifdef HAVE_SYS_PARAM_H 50# include <sys/param.h> 51#endif /* HAVE_SYS_PARAM_H */ 52#ifdef HAVE_SYS_UCRED_H 53# include <sys/ucred.h> 54typedef struct xucred cupsd_ucred_t; 55# define CUPSD_UCRED_UID(c) (c).cr_uid 56#else 57# ifndef __OpenBSD__ 58typedef struct ucred cupsd_ucred_t; 59# else 60typedef struct sockpeercred cupsd_ucred_t; 61# endif 62# define CUPSD_UCRED_UID(c) (c).uid 63#endif /* HAVE_SYS_UCRED_H */ 64 65 66/* 67 * Local functions... 68 */ 69 70#ifdef HAVE_AUTHORIZATION_H 71static int check_authref(cupsd_client_t *con, const char *right); 72#endif /* HAVE_AUTHORIZATION_H */ 73static int compare_locations(cupsd_location_t *a, 74 cupsd_location_t *b); 75static cupsd_authmask_t *copy_authmask(cupsd_authmask_t *am, void *data); 76#if !HAVE_LIBPAM 77static char *cups_crypt(const char *pw, const char *salt); 78#endif /* !HAVE_LIBPAM */ 79static void free_authmask(cupsd_authmask_t *am, void *data); 80#if HAVE_LIBPAM 81static int pam_func(int, const struct pam_message **, 82 struct pam_response **, void *); 83#else 84static void to64(char *s, unsigned long v, int n); 85#endif /* HAVE_LIBPAM */ 86 87 88/* 89 * Local structures... 90 */ 91 92#if HAVE_LIBPAM 93typedef struct cupsd_authdata_s /**** Authentication data ****/ 94{ 95 char username[HTTP_MAX_VALUE], /* Username string */ 96 password[HTTP_MAX_VALUE]; /* Password string */ 97} cupsd_authdata_t; 98#endif /* HAVE_LIBPAM */ 99 100 101/* 102 * 'cupsdAddIPMask()' - Add an IP address authorization mask. 103 */ 104 105int /* O - 1 on success, 0 on failure */ 106cupsdAddIPMask( 107 cups_array_t **masks, /* IO - Masks array (created as needed) */ 108 const unsigned address[4], /* I - IP address */ 109 const unsigned netmask[4]) /* I - IP netmask */ 110{ 111 cupsd_authmask_t temp; /* New host/domain mask */ 112 113 114 cupsdLogMessage(CUPSD_LOG_DEBUG2, 115 "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, " 116 "netmask=%x:%x:%x:%x)", 117 masks, *masks, 118 address[0], address[1], address[2], address[3], 119 netmask[0], netmask[1], netmask[2], netmask[3]); 120 121 temp.type = CUPSD_AUTH_IP; 122 memcpy(temp.mask.ip.address, address, sizeof(temp.mask.ip.address)); 123 memcpy(temp.mask.ip.netmask, netmask, sizeof(temp.mask.ip.netmask)); 124 125 /* 126 * Create the masks array as needed and add... 127 */ 128 129 if (!*masks) 130 *masks = cupsArrayNew3(NULL, NULL, NULL, 0, 131 (cups_acopy_func_t)copy_authmask, 132 (cups_afree_func_t)free_authmask); 133 134 return (cupsArrayAdd(*masks, &temp)); 135} 136 137 138/* 139 * 'cupsdAddLocation()' - Add a location for authorization. 140 */ 141 142void 143cupsdAddLocation(cupsd_location_t *loc) /* I - Location to add */ 144{ 145 /* 146 * Make sure the locations array is created... 147 */ 148 149 if (!Locations) 150 Locations = cupsArrayNew3((cups_array_func_t)compare_locations, NULL, 151 (cups_ahash_func_t)NULL, 0, 152 (cups_acopy_func_t)NULL, 153 (cups_afree_func_t)cupsdFreeLocation); 154 155 if (Locations) 156 { 157 cupsArrayAdd(Locations, loc); 158 159 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddLocation: Added location \"%s\"", 160 loc->location ? loc->location : "(null)"); 161 } 162} 163 164 165/* 166 * 'cupsdAddName()' - Add a name to a location... 167 */ 168 169void 170cupsdAddName(cupsd_location_t *loc, /* I - Location to add to */ 171 char *name) /* I - Name to add */ 172{ 173 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")", 174 loc, name); 175 176 if (!loc->names) 177 loc->names = cupsArrayNew3(NULL, NULL, NULL, 0, 178 (cups_acopy_func_t)_cupsStrAlloc, 179 (cups_afree_func_t)_cupsStrFree); 180 181 if (!cupsArrayAdd(loc->names, name)) 182 { 183 cupsdLogMessage(CUPSD_LOG_ERROR, 184 "Unable to duplicate name for location %s: %s", 185 loc->location ? loc->location : "nil", strerror(errno)); 186 return; 187 } 188} 189 190 191/* 192 * 'cupsdAddNameMask()' - Add a host or interface name authorization mask. 193 */ 194 195int /* O - 1 on success, 0 on failure */ 196cupsdAddNameMask(cups_array_t **masks, /* IO - Masks array (created as needed) */ 197 char *name) /* I - Host or interface name */ 198{ 199 cupsd_authmask_t temp; /* New host/domain mask */ 200 char ifname[32], /* Interface name */ 201 *ifptr; /* Pointer to end of name */ 202 203 204 cupsdLogMessage(CUPSD_LOG_DEBUG2, 205 "cupsdAddNameMask(masks=%p(%p), name=\"%s\")", 206 masks, *masks, name); 207 208 if (!_cups_strcasecmp(name, "@LOCAL")) 209 { 210 /* 211 * Deny *interface*... 212 */ 213 214 temp.type = CUPSD_AUTH_INTERFACE; 215 temp.mask.name.name = (char *)"*"; 216 } 217 else if (!_cups_strncasecmp(name, "@IF(", 4)) 218 { 219 /* 220 * Deny *interface*... 221 */ 222 223 strlcpy(ifname, name + 4, sizeof(ifname)); 224 225 ifptr = ifname + strlen(ifname) - 1; 226 227 if (ifptr >= ifname && *ifptr == ')') 228 { 229 ifptr --; 230 *ifptr = '\0'; 231 } 232 233 temp.type = CUPSD_AUTH_INTERFACE; 234 temp.mask.name.name = ifname; 235 } 236 else 237 { 238 /* 239 * Deny name... 240 */ 241 242 if (*name == '*') 243 name ++; 244 245 temp.type = CUPSD_AUTH_NAME; 246 temp.mask.name.name = (char *)name; 247 } 248 249 /* 250 * Set the name length... 251 */ 252 253 temp.mask.name.length = strlen(temp.mask.name.name); 254 255 /* 256 * Create the masks array as needed and add... 257 */ 258 259 if (!*masks) 260 *masks = cupsArrayNew3(NULL, NULL, NULL, 0, 261 (cups_acopy_func_t)copy_authmask, 262 (cups_afree_func_t)free_authmask); 263 264 return (cupsArrayAdd(*masks, &temp)); 265} 266 267 268/* 269 * 'cupsdAuthorize()' - Validate any authorization credentials. 270 */ 271 272void 273cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ 274{ 275 int type; /* Authentication type */ 276 const char *authorization; /* Pointer into Authorization string */ 277 char *ptr, /* Pointer into string */ 278 username[HTTP_MAX_VALUE], 279 /* Username string */ 280 password[HTTP_MAX_VALUE]; 281 /* Password string */ 282 cupsd_cert_t *localuser; /* Certificate username */ 283 284 285 /* 286 * Locate the best matching location so we know what kind of 287 * authentication to expect... 288 */ 289 290 con->best = cupsdFindBest(con->uri, httpGetState(con->http)); 291 con->type = CUPSD_AUTH_NONE; 292 293 cupsdLogMessage(CUPSD_LOG_DEBUG2, 294 "[Client %d] con->uri=\"%s\", con->best=%p(%s)", 295 con->number, con->uri, con->best, 296 con->best ? con->best->location : ""); 297 298 if (con->best && con->best->type != CUPSD_AUTH_NONE) 299 { 300 if (con->best->type == CUPSD_AUTH_DEFAULT) 301 type = cupsdDefaultAuthType(); 302 else 303 type = con->best->type; 304 } 305 else 306 type = cupsdDefaultAuthType(); 307 308 /* 309 * Decode the Authorization string... 310 */ 311 312 authorization = httpGetField(con->http, HTTP_FIELD_AUTHORIZATION); 313 314 cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Client %d] Authorization=\"%s\"", 315 con->number, authorization); 316 317 username[0] = '\0'; 318 password[0] = '\0'; 319 320#ifdef HAVE_GSSAPI 321 con->gss_uid = 0; 322#endif /* HAVE_GSSAPI */ 323 324#ifdef HAVE_AUTHORIZATION_H 325 if (con->authref) 326 { 327 AuthorizationFree(con->authref, kAuthorizationFlagDefaults); 328 con->authref = NULL; 329 } 330#endif /* HAVE_AUTHORIZATION_H */ 331 332 if (!*authorization) 333 { 334 /* 335 * No authorization data provided, return early... 336 */ 337 338 cupsdLogMessage(CUPSD_LOG_DEBUG, 339 "[Client %d] No authentication data provided.", 340 con->number); 341 return; 342 } 343#ifdef HAVE_AUTHORIZATION_H 344 else if (!strncmp(authorization, "AuthRef ", 8) && 345 httpAddrLocalhost(httpGetAddress(con->http))) 346 { 347 OSStatus status; /* Status */ 348 char authdata[HTTP_MAX_VALUE]; 349 /* Nonce value from client */ 350 int authlen; /* Auth string length */ 351 AuthorizationItemSet *authinfo; /* Authorization item set */ 352 353 /* 354 * Get the Authorization Services data... 355 */ 356 357 authorization += 8; 358 while (isspace(*authorization & 255)) 359 authorization ++; 360 361 authlen = sizeof(authdata); 362 httpDecode64_2(authdata, &authlen, authorization); 363 364 if (authlen != kAuthorizationExternalFormLength) 365 { 366 cupsdLogMessage(CUPSD_LOG_ERROR, 367 "[Client %d] External Authorization reference size is " 368 "incorrect.", con->number); 369 return; 370 } 371 372 if ((status = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)authdata, &con->authref)) != 0) 373 { 374 cupsdLogMessage(CUPSD_LOG_ERROR, 375 "[Client %d] AuthorizationCreateFromExternalForm " 376 "returned %d (%s)", con->number, (int)status, 377 cssmErrorString(status)); 378 return; 379 } 380 381 username[0] = '\0'; 382 383 if (!AuthorizationCopyInfo(con->authref, kAuthorizationEnvironmentUsername, 384 &authinfo)) 385 { 386 if (authinfo->count == 1 && authinfo->items[0].value && 387 authinfo->items[0].valueLength >= 2) 388 { 389 strlcpy(username, authinfo->items[0].value, sizeof(username)); 390 391 cupsdLogMessage(CUPSD_LOG_DEBUG, 392 "[Client %d] Authorized as \"%s\" using AuthRef", 393 con->number, username); 394 } 395 396 AuthorizationFreeItemSet(authinfo); 397 } 398 399 if (!username[0]) 400 { 401 /* 402 * No username in AuthRef, grab username using peer credentials... 403 */ 404 405 struct passwd *pwd; /* Password entry for this user */ 406 cupsd_ucred_t peercred; /* Peer credentials */ 407 socklen_t peersize; /* Size of peer credentials */ 408 409 peersize = sizeof(peercred); 410 411 if (getsockopt(httpGetFd(con->http), 0, LOCAL_PEERCRED, &peercred, &peersize)) 412 { 413 cupsdLogMessage(CUPSD_LOG_ERROR, 414 "[Client %d] Unable to get peer credentials - %s", 415 con->number, strerror(errno)); 416 return; 417 } 418 419 if ((pwd = getpwuid(CUPSD_UCRED_UID(peercred))) == NULL) 420 { 421 cupsdLogMessage(CUPSD_LOG_ERROR, 422 "[Client %d] Unable to find UID %d for peer " 423 "credentials.", con->number, 424 (int)CUPSD_UCRED_UID(peercred)); 425 return; 426 } 427 428 strlcpy(username, pwd->pw_name, sizeof(username)); 429 430 cupsdLogMessage(CUPSD_LOG_DEBUG, 431 "[Client %d] Authorized as \"%s\" using " 432 "AuthRef + PeerCred", con->number, username); 433 } 434 435 con->type = CUPSD_AUTH_BASIC; 436 } 437#endif /* HAVE_AUTHORIZATION_H */ 438#if defined(SO_PEERCRED) && defined(AF_LOCAL) 439 else if (!strncmp(authorization, "PeerCred ", 9) && 440 con->http->hostaddr->addr.sa_family == AF_LOCAL && con->best) 441 { 442 /* 443 * Use peer credentials from domain socket connection... 444 */ 445 446 struct passwd *pwd; /* Password entry for this user */ 447 cupsd_ucred_t peercred; /* Peer credentials */ 448 socklen_t peersize; /* Size of peer credentials */ 449#ifdef HAVE_AUTHORIZATION_H 450 const char *name; /* Authorizing name */ 451 int no_peer = 0; /* Don't allow peer credentials? */ 452 453 /* 454 * See if we should allow peer credentials... 455 */ 456 457 for (name = (char *)cupsArrayFirst(con->best->names); 458 name; 459 name = (char *)cupsArrayNext(con->best->names)) 460 { 461 if (!_cups_strncasecmp(name, "@AUTHKEY(", 9) || 462 !_cups_strcasecmp(name, "@SYSTEM")) 463 { 464 /* Normally don't want peer credentials if we need an auth key... */ 465 no_peer = 1; 466 } 467 else if (!_cups_strcasecmp(name, "@OWNER")) 468 { 469 /* but if @OWNER is present then we allow it... */ 470 no_peer = 0; 471 break; 472 } 473 } 474 475 if (no_peer) 476 { 477 cupsdLogMessage(CUPSD_LOG_ERROR, 478 "[Client %d] PeerCred authentication not allowed for " 479 "resource per AUTHKEY policy.", con->number); 480 return; 481 } 482#endif /* HAVE_AUTHORIZATION_H */ 483 484 if ((pwd = getpwnam(authorization + 9)) == NULL) 485 { 486 cupsdLogMessage(CUPSD_LOG_ERROR, 487 "[Client %d] User \"%s\" does not exist.", con->number, 488 authorization + 9); 489 return; 490 } 491 492 peersize = sizeof(peercred); 493 494# ifdef __APPLE__ 495 if (getsockopt(httpGetFd(con->http), 0, LOCAL_PEERCRED, &peercred, &peersize)) 496# else 497 if (getsockopt(httpGetFd(con->http), SOL_SOCKET, SO_PEERCRED, &peercred, &peersize)) 498# endif /* __APPLE__ */ 499 { 500 cupsdLogMessage(CUPSD_LOG_ERROR, 501 "[Client %d] Unable to get peer credentials - %s", 502 con->number, strerror(errno)); 503 return; 504 } 505 506 if (pwd->pw_uid != CUPSD_UCRED_UID(peercred)) 507 { 508 cupsdLogMessage(CUPSD_LOG_ERROR, 509 "[Client %d] Invalid peer credentials for \"%s\" - got " 510 "%d, expected %d!", con->number, authorization + 9, 511 CUPSD_UCRED_UID(peercred), pwd->pw_uid); 512# ifdef HAVE_SYS_UCRED_H 513 cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_version=%d", 514 con->number, peercred.cr_version); 515 cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_uid=%d", 516 con->number, peercred.cr_uid); 517 cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_ngroups=%d", 518 con->number, peercred.cr_ngroups); 519 cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_groups[0]=%d", 520 con->number, peercred.cr_groups[0]); 521# endif /* HAVE_SYS_UCRED_H */ 522 return; 523 } 524 525 strlcpy(username, authorization + 9, sizeof(username)); 526 527# ifdef HAVE_GSSAPI 528 con->gss_uid = CUPSD_UCRED_UID(peercred); 529# endif /* HAVE_GSSAPI */ 530 531 cupsdLogMessage(CUPSD_LOG_DEBUG, 532 "[Client %d] Authorized as %s using PeerCred", con->number, 533 username); 534 535 con->type = CUPSD_AUTH_BASIC; 536 } 537#endif /* SO_PEERCRED && AF_LOCAL */ 538 else if (!strncmp(authorization, "Local", 5) && 539 httpAddrLocalhost(httpGetAddress(con->http))) 540 { 541 /* 542 * Get Local certificate authentication data... 543 */ 544 545 authorization += 5; 546 while (isspace(*authorization & 255)) 547 authorization ++; 548 549 if ((localuser = cupsdFindCert(authorization)) == NULL) 550 { 551 cupsdLogMessage(CUPSD_LOG_ERROR, 552 "[Client %d] Local authentication certificate not found.", 553 con->number); 554 return; 555 } 556 557 strlcpy(username, localuser->username, sizeof(username)); 558 con->type = localuser->type; 559 560 cupsdLogMessage(CUPSD_LOG_DEBUG, 561 "[Client %d] Authorized as %s using Local", con->number, 562 username); 563 } 564 else if (!strncmp(authorization, "Basic", 5)) 565 { 566 /* 567 * Get the Basic authentication data... 568 */ 569 570 int userlen; /* Username:password length */ 571 572 573 authorization += 5; 574 while (isspace(*authorization & 255)) 575 authorization ++; 576 577 userlen = sizeof(username); 578 httpDecode64_2(username, &userlen, authorization); 579 580 /* 581 * Pull the username and password out... 582 */ 583 584 if ((ptr = strchr(username, ':')) == NULL) 585 { 586 cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Missing Basic password.", 587 con->number); 588 return; 589 } 590 591 *ptr++ = '\0'; 592 593 if (!username[0]) 594 { 595 /* 596 * Username must not be empty... 597 */ 598 599 cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Empty Basic username.", 600 con->number); 601 return; 602 } 603 604 if (!*ptr) 605 { 606 /* 607 * Password must not be empty... 608 */ 609 610 cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Empty Basic password.", 611 con->number); 612 return; 613 } 614 615 strlcpy(password, ptr, sizeof(password)); 616 617 /* 618 * Validate the username and password... 619 */ 620 621 switch (type) 622 { 623 default : 624 case CUPSD_AUTH_BASIC : 625 { 626#if HAVE_LIBPAM 627 /* 628 * Only use PAM to do authentication. This supports MD5 629 * passwords, among other things... 630 */ 631 632 pam_handle_t *pamh; /* PAM authentication handle */ 633 int pamerr; /* PAM error code */ 634 struct pam_conv pamdata;/* PAM conversation data */ 635 cupsd_authdata_t data; /* Authentication data */ 636 637 638 strlcpy(data.username, username, sizeof(data.username)); 639 strlcpy(data.password, password, sizeof(data.password)); 640 641# ifdef __sun 642 pamdata.conv = (int (*)(int, struct pam_message **, 643 struct pam_response **, 644 void *))pam_func; 645# else 646 pamdata.conv = pam_func; 647# endif /* __sun */ 648 pamdata.appdata_ptr = &data; 649 650 pamerr = pam_start("cups", username, &pamdata, &pamh); 651 if (pamerr != PAM_SUCCESS) 652 { 653 cupsdLogMessage(CUPSD_LOG_ERROR, 654 "[Client %d] pam_start() returned %d (%s)", 655 con->number, pamerr, pam_strerror(pamh, pamerr)); 656 return; 657 } 658 659# ifdef HAVE_PAM_SET_ITEM 660# ifdef PAM_RHOST 661 pamerr = pam_set_item(pamh, PAM_RHOST, con->http->hostname); 662 if (pamerr != PAM_SUCCESS) 663 cupsdLogMessage(CUPSD_LOG_WARN, 664 "[Client %d] pam_set_item(PAM_RHOST) " 665 "returned %d (%s)", con->number, pamerr, 666 pam_strerror(pamh, pamerr)); 667# endif /* PAM_RHOST */ 668 669# ifdef PAM_TTY 670 pamerr = pam_set_item(pamh, PAM_TTY, "cups"); 671 if (pamerr != PAM_SUCCESS) 672 cupsdLogMessage(CUPSD_LOG_WARN, 673 "[Client %d] pam_set_item(PAM_TTY) " 674 "returned %d (%s)!", con->number, pamerr, 675 pam_strerror(pamh, pamerr)); 676# endif /* PAM_TTY */ 677# endif /* HAVE_PAM_SET_ITEM */ 678 679 pamerr = pam_authenticate(pamh, PAM_SILENT); 680 if (pamerr != PAM_SUCCESS) 681 { 682 cupsdLogMessage(CUPSD_LOG_ERROR, 683 "[Client %d] pam_authenticate() returned %d (%s)", 684 con->number, pamerr, pam_strerror(pamh, pamerr)); 685 pam_end(pamh, 0); 686 return; 687 } 688 689# ifdef HAVE_PAM_SETCRED 690 pamerr = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); 691 if (pamerr != PAM_SUCCESS) 692 cupsdLogMessage(CUPSD_LOG_WARN, 693 "[Client %d] pam_setcred() returned %d (%s)", 694 con->number, pamerr, 695 pam_strerror(pamh, pamerr)); 696# endif /* HAVE_PAM_SETCRED */ 697 698 pamerr = pam_acct_mgmt(pamh, PAM_SILENT); 699 if (pamerr != PAM_SUCCESS) 700 { 701 cupsdLogMessage(CUPSD_LOG_ERROR, 702 "[Client %d] pam_acct_mgmt() returned %d (%s)", 703 con->number, pamerr, pam_strerror(pamh, pamerr)); 704 pam_end(pamh, 0); 705 return; 706 } 707 708 pam_end(pamh, PAM_SUCCESS); 709 710#else 711 /* 712 * Use normal UNIX password file-based authentication... 713 */ 714 715 char *pass; /* Encrypted password */ 716 struct passwd *pw; /* User password data */ 717# ifdef HAVE_SHADOW_H 718 struct spwd *spw; /* Shadow password data */ 719# endif /* HAVE_SHADOW_H */ 720 721 722 pw = getpwnam(username); /* Get the current password */ 723 endpwent(); /* Close the password file */ 724 725 if (!pw) 726 { 727 /* 728 * No such user... 729 */ 730 731 cupsdLogMessage(CUPSD_LOG_ERROR, 732 "[Client %d] Unknown username \"%s\".", 733 con->number, username); 734 return; 735 } 736 737# ifdef HAVE_SHADOW_H 738 spw = getspnam(username); 739 endspent(); 740 741 if (!spw && !strcmp(pw->pw_passwd, "x")) 742 { 743 /* 744 * Don't allow blank passwords! 745 */ 746 747 cupsdLogMessage(CUPSD_LOG_ERROR, 748 "[Client %d] Username \"%s\" has no shadow " 749 "password.", con->number, username); 750 return; 751 } 752 753 if (spw && !spw->sp_pwdp[0] && !pw->pw_passwd[0]) 754# else 755 if (!pw->pw_passwd[0]) 756# endif /* HAVE_SHADOW_H */ 757 { 758 /* 759 * Don't allow blank passwords! 760 */ 761 762 cupsdLogMessage(CUPSD_LOG_ERROR, 763 "[Client %d] Username \"%s\" has no password.", 764 con->number, username); 765 return; 766 } 767 768 /* 769 * OK, the password isn't blank, so compare with what came from the 770 * client... 771 */ 772 773 pass = cups_crypt(password, pw->pw_passwd); 774 775 cupsdLogMessage(CUPSD_LOG_DEBUG2, 776 "[Client %d] pw_passwd=\"%s\", crypt=\"%s\"", 777 con->number, pw->pw_passwd, pass); 778 779 if (!pass || strcmp(pw->pw_passwd, pass)) 780 { 781# ifdef HAVE_SHADOW_H 782 if (spw) 783 { 784 pass = cups_crypt(password, spw->sp_pwdp); 785 786 cupsdLogMessage(CUPSD_LOG_DEBUG2, 787 "[Client %d] sp_pwdp=\"%s\", crypt=\"%s\"", 788 con->number, spw->sp_pwdp, pass); 789 790 if (pass == NULL || strcmp(spw->sp_pwdp, pass)) 791 { 792 cupsdLogMessage(CUPSD_LOG_ERROR, 793 "[Client %d] Authentication failed for user " 794 "\"%s\".", con->number, username); 795 return; 796 } 797 } 798 else 799# endif /* HAVE_SHADOW_H */ 800 { 801 cupsdLogMessage(CUPSD_LOG_ERROR, 802 "[Client %d] Authentication failed for user " 803 "\"%s\".", con->number, username); 804 return; 805 } 806 } 807#endif /* HAVE_LIBPAM */ 808 } 809 810 cupsdLogMessage(CUPSD_LOG_DEBUG, 811 "[Client %d] Authorized as %s using Basic", 812 con->number, username); 813 break; 814 } 815 816 con->type = type; 817 } 818#ifdef HAVE_GSSAPI 819 else if (!strncmp(authorization, "Negotiate", 9)) 820 { 821 int len; /* Length of authorization string */ 822 gss_ctx_id_t context; /* Authorization context */ 823 OM_uint32 major_status, /* Major status code */ 824 minor_status; /* Minor status code */ 825 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER, 826 /* Input token from string */ 827 output_token = GSS_C_EMPTY_BUFFER; 828 /* Output token for username */ 829 gss_name_t client_name; /* Client name */ 830 831 832# ifdef __APPLE__ 833 /* 834 * If the weak-linked GSSAPI/Kerberos library is not present, don't try 835 * to use it... 836 */ 837 838 if (gss_init_sec_context == NULL) 839 { 840 cupsdLogMessage(CUPSD_LOG_WARN, 841 "[Client %d] GSSAPI/Kerberos authentication failed " 842 "because the Kerberos framework is not present.", 843 con->number); 844 return; 845 } 846# endif /* __APPLE__ */ 847 848 /* 849 * Find the start of the Kerberos input token... 850 */ 851 852 authorization += 9; 853 while (isspace(*authorization & 255)) 854 authorization ++; 855 856 if (!*authorization) 857 { 858 cupsdLogMessage(CUPSD_LOG_DEBUG2, 859 "[Client %d] No authentication data specified.", 860 con->number); 861 return; 862 } 863 864 /* 865 * Decode the authorization string to get the input token... 866 */ 867 868 len = (int)strlen(authorization); 869 input_token.value = malloc((size_t)len); 870 input_token.value = httpDecode64_2(input_token.value, &len, 871 authorization); 872 input_token.length = (size_t)len; 873 874 /* 875 * Accept the input token to get the authorization info... 876 */ 877 878 context = GSS_C_NO_CONTEXT; 879 client_name = GSS_C_NO_NAME; 880 major_status = gss_accept_sec_context(&minor_status, 881 &context, 882 ServerCreds, 883 &input_token, 884 GSS_C_NO_CHANNEL_BINDINGS, 885 &client_name, 886 NULL, 887 &output_token, 888 NULL, 889 NULL, 890 NULL); 891 892 if (output_token.length > 0) 893 gss_release_buffer(&minor_status, &output_token); 894 895 if (GSS_ERROR(major_status)) 896 { 897 cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, 898 "[Client %d] Error accepting GSSAPI security context", 899 con->number); 900 901 if (context != GSS_C_NO_CONTEXT) 902 gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); 903 return; 904 } 905 906 con->have_gss = 1; 907 908 /* 909 * Get the username associated with the client's credentials... 910 */ 911 912 if (major_status == GSS_S_CONTINUE_NEEDED) 913 cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, 914 "[Client %d] Credentials not complete", con->number); 915 else if (major_status == GSS_S_COMPLETE) 916 { 917 major_status = gss_display_name(&minor_status, client_name, 918 &output_token, NULL); 919 920 if (GSS_ERROR(major_status)) 921 { 922 cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, 923 "[Client %d] Error getting username", con->number); 924 gss_release_name(&minor_status, &client_name); 925 gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); 926 return; 927 } 928 929 strlcpy(username, output_token.value, sizeof(username)); 930 931 cupsdLogMessage(CUPSD_LOG_DEBUG, 932 "[Client %d] Authorized as %s using Negotiate", 933 con->number, username); 934 935 gss_release_name(&minor_status, &client_name); 936 gss_release_buffer(&minor_status, &output_token); 937 938 con->type = CUPSD_AUTH_NEGOTIATE; 939 } 940 941 gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); 942 943# if defined(SO_PEERCRED) && defined(AF_LOCAL) 944 /* 945 * Get the client's UID if we are printing locally - that allows a backend 946 * to run as the correct user to get Kerberos credentials of its own. 947 */ 948 949 if (httpAddrFamily(con->http->hostaddr) == AF_LOCAL) 950 { 951 cupsd_ucred_t peercred; /* Peer credentials */ 952 socklen_t peersize; /* Size of peer credentials */ 953 954 peersize = sizeof(peercred); 955 956# ifdef __APPLE__ 957 if (getsockopt(httpGetFd(con->http), 0, LOCAL_PEERCRED, &peercred, &peersize)) 958# else 959 if (getsockopt(httpGetFd(con->http), SOL_SOCKET, SO_PEERCRED, &peercred, 960 &peersize)) 961# endif /* __APPLE__ */ 962 { 963 cupsdLogMessage(CUPSD_LOG_ERROR, 964 "[Client %d] Unable to get peer credentials - %s", 965 con->number, strerror(errno)); 966 } 967 else 968 { 969 cupsdLogMessage(CUPSD_LOG_DEBUG, 970 "[Client %d] Using credentials for UID %d.", 971 con->number, CUPSD_UCRED_UID(peercred)); 972 con->gss_uid = CUPSD_UCRED_UID(peercred); 973 } 974 } 975# endif /* SO_PEERCRED && AF_LOCAL */ 976 } 977#endif /* HAVE_GSSAPI */ 978 else 979 { 980 char scheme[256]; /* Auth scheme... */ 981 982 983 if (sscanf(authorization, "%255s", scheme) != 1) 984 strlcpy(scheme, "UNKNOWN", sizeof(scheme)); 985 986 cupsdLogMessage(CUPSD_LOG_ERROR, 987 "[Client %d] Bad authentication data \"%s ...\"", 988 con->number, scheme); 989 return; 990 } 991 992 /* 993 * If we get here, then we were able to validate the username and 994 * password - copy the validated username and password to the client 995 * data and return... 996 */ 997 998 strlcpy(con->username, username, sizeof(con->username)); 999 strlcpy(con->password, password, sizeof(con->password)); 1000} 1001 1002 1003/* 1004 * 'cupsdCheckAccess()' - Check whether the given address is allowed to 1005 * access a location. 1006 */ 1007 1008int /* O - 1 if allowed, 0 otherwise */ 1009cupsdCheckAccess( 1010 unsigned ip[4], /* I - Client address */ 1011 const char *name, /* I - Client hostname */ 1012 size_t namelen, /* I - Length of hostname */ 1013 cupsd_location_t *loc) /* I - Location to check */ 1014{ 1015 int allow; /* 1 if allowed, 0 otherwise */ 1016 1017 1018 if (!_cups_strcasecmp(name, "localhost")) 1019 { 1020 /* 1021 * Access from localhost (127.0.0.1 or ::1) is always allowed... 1022 */ 1023 1024 return (1); 1025 } 1026 else 1027 { 1028 /* 1029 * Do authorization checks on the domain/address... 1030 */ 1031 1032 switch (loc->order_type) 1033 { 1034 default : 1035 allow = 0; /* anti-compiler-warning-code */ 1036 break; 1037 1038 case CUPSD_AUTH_ALLOW : /* Order Deny,Allow */ 1039 allow = 1; 1040 1041 if (cupsdCheckAuth(ip, name, namelen, loc->deny)) 1042 allow = 0; 1043 1044 if (cupsdCheckAuth(ip, name, namelen, loc->allow)) 1045 allow = 1; 1046 break; 1047 1048 case CUPSD_AUTH_DENY : /* Order Allow,Deny */ 1049 allow = 0; 1050 1051 if (cupsdCheckAuth(ip, name, namelen, loc->allow)) 1052 allow = 1; 1053 1054 if (cupsdCheckAuth(ip, name, namelen, loc->deny)) 1055 allow = 0; 1056 break; 1057 } 1058 } 1059 1060 return (allow); 1061} 1062 1063 1064/* 1065 * 'cupsdCheckAuth()' - Check authorization masks. 1066 */ 1067 1068int /* O - 1 if mask matches, 0 otherwise */ 1069cupsdCheckAuth(unsigned ip[4], /* I - Client address */ 1070 const char *name, /* I - Client hostname */ 1071 size_t name_len, /* I - Length of hostname */ 1072 cups_array_t *masks) /* I - Masks */ 1073{ 1074 int i; /* Looping var */ 1075 cupsd_authmask_t *mask; /* Current mask */ 1076 cupsd_netif_t *iface; /* Network interface */ 1077 unsigned netip4; /* IPv4 network address */ 1078#ifdef AF_INET6 1079 unsigned netip6[4]; /* IPv6 network address */ 1080#endif /* AF_INET6 */ 1081 1082 1083 for (mask = (cupsd_authmask_t *)cupsArrayFirst(masks); 1084 mask; 1085 mask = (cupsd_authmask_t *)cupsArrayNext(masks)) 1086 { 1087 switch (mask->type) 1088 { 1089 case CUPSD_AUTH_INTERFACE : 1090 /* 1091 * Check for a match with a network interface... 1092 */ 1093 1094 netip4 = htonl(ip[3]); 1095 1096#ifdef AF_INET6 1097 netip6[0] = htonl(ip[0]); 1098 netip6[1] = htonl(ip[1]); 1099 netip6[2] = htonl(ip[2]); 1100 netip6[3] = htonl(ip[3]); 1101#endif /* AF_INET6 */ 1102 1103 cupsdNetIFUpdate(); 1104 1105 if (!strcmp(mask->mask.name.name, "*")) 1106 { 1107#ifdef __APPLE__ 1108 /* 1109 * Allow Back-to-My-Mac addresses... 1110 */ 1111 1112 if ((ip[0] & 0xff000000) == 0xfd000000) 1113 return (1); 1114#endif /* __APPLE__ */ 1115 1116 /* 1117 * Check against all local interfaces... 1118 */ 1119 1120 for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); 1121 iface; 1122 iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) 1123 { 1124 /* 1125 * Only check local interfaces... 1126 */ 1127 1128 if (!iface->is_local) 1129 continue; 1130 1131 if (iface->address.addr.sa_family == AF_INET) 1132 { 1133 /* 1134 * Check IPv4 address... 1135 */ 1136 1137 if ((netip4 & iface->mask.ipv4.sin_addr.s_addr) == 1138 (iface->address.ipv4.sin_addr.s_addr & 1139 iface->mask.ipv4.sin_addr.s_addr)) 1140 return (1); 1141 } 1142#ifdef AF_INET6 1143 else 1144 { 1145 /* 1146 * Check IPv6 address... 1147 */ 1148 1149 for (i = 0; i < 4; i ++) 1150 if ((netip6[i] & iface->mask.ipv6.sin6_addr.s6_addr32[i]) != 1151 (iface->address.ipv6.sin6_addr.s6_addr32[i] & 1152 iface->mask.ipv6.sin6_addr.s6_addr32[i])) 1153 break; 1154 1155 if (i == 4) 1156 return (1); 1157 } 1158#endif /* AF_INET6 */ 1159 } 1160 } 1161 else 1162 { 1163 /* 1164 * Check the named interface... 1165 */ 1166 1167 for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); 1168 iface; 1169 iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) 1170 { 1171 if (strcmp(mask->mask.name.name, iface->name)) 1172 continue; 1173 1174 if (iface->address.addr.sa_family == AF_INET) 1175 { 1176 /* 1177 * Check IPv4 address... 1178 */ 1179 1180 if ((netip4 & iface->mask.ipv4.sin_addr.s_addr) == 1181 (iface->address.ipv4.sin_addr.s_addr & 1182 iface->mask.ipv4.sin_addr.s_addr)) 1183 return (1); 1184 } 1185#ifdef AF_INET6 1186 else 1187 { 1188 /* 1189 * Check IPv6 address... 1190 */ 1191 1192 for (i = 0; i < 4; i ++) 1193 if ((netip6[i] & iface->mask.ipv6.sin6_addr.s6_addr32[i]) != 1194 (iface->address.ipv6.sin6_addr.s6_addr32[i] & 1195 iface->mask.ipv6.sin6_addr.s6_addr32[i])) 1196 break; 1197 1198 if (i == 4) 1199 return (1); 1200 } 1201#endif /* AF_INET6 */ 1202 } 1203 } 1204 break; 1205 1206 case CUPSD_AUTH_NAME : 1207 /* 1208 * Check for exact name match... 1209 */ 1210 1211 if (!_cups_strcasecmp(name, mask->mask.name.name)) 1212 return (1); 1213 1214 /* 1215 * Check for domain match... 1216 */ 1217 1218 if (name_len >= mask->mask.name.length && 1219 mask->mask.name.name[0] == '.' && 1220 !_cups_strcasecmp(name + name_len - mask->mask.name.length, 1221 mask->mask.name.name)) 1222 return (1); 1223 break; 1224 1225 case CUPSD_AUTH_IP : 1226 /* 1227 * Check for IP/network address match... 1228 */ 1229 1230 for (i = 0; i < 4; i ++) 1231 if ((ip[i] & mask->mask.ip.netmask[i]) != 1232 mask->mask.ip.address[i]) 1233 break; 1234 1235 if (i == 4) 1236 return (1); 1237 break; 1238 } 1239 } 1240 1241 return (0); 1242} 1243 1244 1245/* 1246 * 'cupsdCheckGroup()' - Check for a user's group membership. 1247 */ 1248 1249int /* O - 1 if user is a member, 0 otherwise */ 1250cupsdCheckGroup( 1251 const char *username, /* I - User name */ 1252 struct passwd *user, /* I - System user info */ 1253 const char *groupname) /* I - Group name */ 1254{ 1255 int i; /* Looping var */ 1256 struct group *group; /* System group info */ 1257#ifdef HAVE_MBR_UID_TO_UUID 1258 uuid_t useruuid, /* UUID for username */ 1259 groupuuid; /* UUID for groupname */ 1260 int is_member; /* True if user is a member of group */ 1261#endif /* HAVE_MBR_UID_TO_UUID */ 1262 1263 1264 cupsdLogMessage(CUPSD_LOG_DEBUG2, 1265 "cupsdCheckGroup(username=\"%s\", user=%p, groupname=\"%s\")", 1266 username, user, groupname); 1267 1268 /* 1269 * Validate input... 1270 */ 1271 1272 if (!username || !groupname) 1273 return (0); 1274 1275 /* 1276 * Check to see if the user is a member of the named group... 1277 */ 1278 1279 group = getgrnam(groupname); 1280 endgrent(); 1281 1282 if (group != NULL) 1283 { 1284 /* 1285 * Group exists, check it... 1286 */ 1287 1288 for (i = 0; group->gr_mem[i]; i ++) 1289 if (!_cups_strcasecmp(username, group->gr_mem[i])) 1290 return (1); 1291 } 1292 1293 /* 1294 * Group doesn't exist or user not in group list, check the group ID 1295 * against the user's group ID... 1296 */ 1297 1298 if (user && group && group->gr_gid == user->pw_gid) 1299 return (1); 1300 1301#ifdef HAVE_MBR_UID_TO_UUID 1302 /* 1303 * Check group membership through MacOS X membership API... 1304 */ 1305 1306 if (user && !mbr_uid_to_uuid(user->pw_uid, useruuid)) 1307 { 1308 if (group) 1309 { 1310 /* 1311 * Map group name to UUID and check membership... 1312 */ 1313 1314 if (!mbr_gid_to_uuid(group->gr_gid, groupuuid)) 1315 if (!mbr_check_membership(useruuid, groupuuid, &is_member)) 1316 if (is_member) 1317 return (1); 1318 } 1319 else if (groupname[0] == '#') 1320 { 1321 /* 1322 * Use UUID directly and check for equality (user UUID) and 1323 * membership (group UUID)... 1324 */ 1325 1326 if (!uuid_parse((char *)groupname + 1, groupuuid)) 1327 { 1328 if (!uuid_compare(useruuid, groupuuid)) 1329 return (1); 1330 else if (!mbr_check_membership(useruuid, groupuuid, &is_member)) 1331 if (is_member) 1332 return (1); 1333 } 1334 1335 return (0); 1336 } 1337 } 1338 else if (groupname[0] == '#') 1339 return (0); 1340#endif /* HAVE_MBR_UID_TO_UUID */ 1341 1342 /* 1343 * If we get this far, then the user isn't part of the named group... 1344 */ 1345 1346 return (0); 1347} 1348 1349 1350/* 1351 * 'cupsdCopyLocation()' - Make a copy of a location... 1352 */ 1353 1354cupsd_location_t * /* O - New location */ 1355cupsdCopyLocation( 1356 cupsd_location_t *loc) /* I - Original location */ 1357{ 1358 cupsd_location_t *temp; /* New location */ 1359 1360 1361 /* 1362 * Make a copy of the original location... 1363 */ 1364 1365 if ((temp = calloc(1, sizeof(cupsd_location_t))) == NULL) 1366 return (NULL); 1367 1368 /* 1369 * Copy the information from the original location to the new one. 1370 */ 1371 1372 if (!loc) 1373 return (temp); 1374 1375 if (loc->location) 1376 temp->location = _cupsStrAlloc(loc->location); 1377 1378 temp->limit = loc->limit; 1379 temp->order_type = loc->order_type; 1380 temp->type = loc->type; 1381 temp->level = loc->level; 1382 temp->satisfy = loc->satisfy; 1383 temp->encryption = loc->encryption; 1384 1385 if (loc->names) 1386 { 1387 if ((temp->names = cupsArrayDup(loc->names)) == NULL) 1388 { 1389 cupsdLogMessage(CUPSD_LOG_ERROR, 1390 "Unable to allocate memory for %d names: %s", 1391 cupsArrayCount(loc->names), strerror(errno)); 1392 1393 cupsdFreeLocation(temp); 1394 return (NULL); 1395 } 1396 } 1397 1398 if (loc->allow) 1399 { 1400 /* 1401 * Copy allow rules... 1402 */ 1403 1404 if ((temp->allow = cupsArrayDup(loc->allow)) == NULL) 1405 { 1406 cupsdLogMessage(CUPSD_LOG_ERROR, 1407 "Unable to allocate memory for %d allow rules: %s", 1408 cupsArrayCount(loc->allow), strerror(errno)); 1409 cupsdFreeLocation(temp); 1410 return (NULL); 1411 } 1412 } 1413 1414 if (loc->deny) 1415 { 1416 /* 1417 * Copy deny rules... 1418 */ 1419 1420 if ((temp->deny = cupsArrayDup(loc->deny)) == NULL) 1421 { 1422 cupsdLogMessage(CUPSD_LOG_ERROR, 1423 "Unable to allocate memory for %d deny rules: %s", 1424 cupsArrayCount(loc->deny), strerror(errno)); 1425 cupsdFreeLocation(temp); 1426 return (NULL); 1427 } 1428 } 1429 1430 return (temp); 1431} 1432 1433 1434/* 1435 * 'cupsdDeleteAllLocations()' - Free all memory used for location authorization. 1436 */ 1437 1438void 1439cupsdDeleteAllLocations(void) 1440{ 1441 /* 1442 * Free the location array, which will free all of the locations... 1443 */ 1444 1445 cupsArrayDelete(Locations); 1446 Locations = NULL; 1447} 1448 1449 1450/* 1451 * 'cupsdFindBest()' - Find the location entry that best matches the resource. 1452 */ 1453 1454cupsd_location_t * /* O - Location that matches */ 1455cupsdFindBest(const char *path, /* I - Resource path */ 1456 http_state_t state) /* I - HTTP state/request */ 1457{ 1458 char uri[HTTP_MAX_URI], 1459 /* URI in request... */ 1460 *uriptr; /* Pointer into URI */ 1461 cupsd_location_t *loc, /* Current location */ 1462 *best; /* Best match for location so far */ 1463 size_t bestlen; /* Length of best match */ 1464 int limit; /* Limit field */ 1465 static const int limits[] = /* Map http_status_t to CUPSD_AUTH_LIMIT_xyz */ 1466 { 1467 CUPSD_AUTH_LIMIT_ALL, 1468 CUPSD_AUTH_LIMIT_OPTIONS, 1469 CUPSD_AUTH_LIMIT_GET, 1470 CUPSD_AUTH_LIMIT_GET, 1471 CUPSD_AUTH_LIMIT_HEAD, 1472 CUPSD_AUTH_LIMIT_POST, 1473 CUPSD_AUTH_LIMIT_POST, 1474 CUPSD_AUTH_LIMIT_POST, 1475 CUPSD_AUTH_LIMIT_PUT, 1476 CUPSD_AUTH_LIMIT_PUT, 1477 CUPSD_AUTH_LIMIT_DELETE, 1478 CUPSD_AUTH_LIMIT_TRACE, 1479 CUPSD_AUTH_LIMIT_ALL, 1480 CUPSD_AUTH_LIMIT_ALL 1481 }; 1482 1483 1484 /* 1485 * First copy the connection URI to a local string so we have drop 1486 * any .ppd extension from the pathname in /printers or /classes 1487 * URIs... 1488 */ 1489 1490 strlcpy(uri, path, sizeof(uri)); 1491 1492 if (!strncmp(uri, "/printers/", 10) || 1493 !strncmp(uri, "/classes/", 9)) 1494 { 1495 /* 1496 * Check if the URI has .ppd on the end... 1497 */ 1498 1499 uriptr = uri + strlen(uri) - 4; /* len > 4 if we get here... */ 1500 1501 if (!strcmp(uriptr, ".ppd")) 1502 *uriptr = '\0'; 1503 } 1504 1505 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: uri = \"%s\"...", uri); 1506 1507 /* 1508 * Loop through the list of locations to find a match... 1509 */ 1510 1511 limit = limits[state]; 1512 best = NULL; 1513 bestlen = 0; 1514 1515 for (loc = (cupsd_location_t *)cupsArrayFirst(Locations); 1516 loc; 1517 loc = (cupsd_location_t *)cupsArrayNext(Locations)) 1518 { 1519 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: Location %s Limit %x", 1520 loc->location ? loc->location : "nil", loc->limit); 1521 1522 if (!strncmp(uri, "/printers/", 10) || !strncmp(uri, "/classes/", 9)) 1523 { 1524 /* 1525 * Use case-insensitive comparison for queue names... 1526 */ 1527 1528 if (loc->length > bestlen && loc->location && 1529 !_cups_strncasecmp(uri, loc->location, loc->length) && 1530 loc->location[0] == '/' && 1531 (limit & loc->limit) != 0) 1532 { 1533 best = loc; 1534 bestlen = loc->length; 1535 } 1536 } 1537 else 1538 { 1539 /* 1540 * Use case-sensitive comparison for other URIs... 1541 */ 1542 1543 if (loc->length > bestlen && loc->location && 1544 !strncmp(uri, loc->location, loc->length) && 1545 loc->location[0] == '/' && 1546 (limit & loc->limit) != 0) 1547 { 1548 best = loc; 1549 bestlen = loc->length; 1550 } 1551 } 1552 } 1553 1554 /* 1555 * Return the match, if any... 1556 */ 1557 1558 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: best = %s", 1559 best ? best->location : "NONE"); 1560 1561 return (best); 1562} 1563 1564 1565/* 1566 * 'cupsdFindLocation()' - Find the named location. 1567 */ 1568 1569cupsd_location_t * /* O - Location that matches */ 1570cupsdFindLocation(const char *location) /* I - Connection */ 1571{ 1572 cupsd_location_t key; /* Search key */ 1573 1574 1575 key.location = (char *)location; 1576 1577 return ((cupsd_location_t *)cupsArrayFind(Locations, &key)); 1578} 1579 1580 1581/* 1582 * 'cupsdFreeLocation()' - Free all memory used by a location. 1583 */ 1584 1585void 1586cupsdFreeLocation(cupsd_location_t *loc)/* I - Location to free */ 1587{ 1588 cupsArrayDelete(loc->names); 1589 cupsArrayDelete(loc->allow); 1590 cupsArrayDelete(loc->deny); 1591 1592 _cupsStrFree(loc->location); 1593 free(loc); 1594} 1595 1596 1597/* 1598 * 'cupsdIsAuthorized()' - Check to see if the user is authorized... 1599 */ 1600 1601http_status_t /* O - HTTP_OK if authorized or error code */ 1602cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ 1603 const char *owner)/* I - Owner of object */ 1604{ 1605 int i, /* Looping vars */ 1606 auth, /* Authorization status */ 1607 type; /* Type of authentication */ 1608 http_addr_t *hostaddr = httpGetAddress(con->http); 1609 /* Client address */ 1610 const char *hostname = httpGetHostname(con->http, NULL, 0); 1611 /* Client hostname */ 1612 unsigned address[4]; /* Authorization address */ 1613 cupsd_location_t *best; /* Best match for location so far */ 1614 size_t hostlen; /* Length of hostname */ 1615 char *name, /* Current username */ 1616 username[256], /* Username to authorize */ 1617 ownername[256], /* Owner name to authorize */ 1618 *ptr; /* Pointer into username */ 1619 struct passwd *pw; /* User password data */ 1620 static const char * const levels[] = /* Auth levels */ 1621 { 1622 "ANON", 1623 "USER", 1624 "GROUP" 1625 }; 1626 static const char * const types[] = /* Auth types */ 1627 { 1628 "None", 1629 "Basic", 1630 "Negotiate" 1631 }; 1632 1633 1634 cupsdLogMessage(CUPSD_LOG_DEBUG2, 1635 "cupsdIsAuthorized: con->uri=\"%s\", con->best=%p(%s)", 1636 con->uri, con->best, con->best ? con->best->location ? 1637 con->best->location : "(null)" : ""); 1638 if (owner) 1639 cupsdLogMessage(CUPSD_LOG_DEBUG2, 1640 "cupsdIsAuthorized: owner=\"%s\"", owner); 1641 1642 /* 1643 * If there is no "best" authentication rule for this request, then 1644 * access is allowed from the local system and denied from other 1645 * addresses... 1646 */ 1647 1648 if (!con->best) 1649 { 1650 if (httpAddrLocalhost(httpGetAddress(con->http)) || 1651 !strcmp(hostname, ServerName) || 1652 cupsArrayFind(ServerAlias, (void *)hostname)) 1653 return (HTTP_OK); 1654 else 1655 return (HTTP_FORBIDDEN); 1656 } 1657 1658 best = con->best; 1659 1660 if ((type = best->type) == CUPSD_AUTH_DEFAULT) 1661 type = cupsdDefaultAuthType(); 1662 1663 cupsdLogMessage(CUPSD_LOG_DEBUG2, 1664 "cupsdIsAuthorized: level=CUPSD_AUTH_%s, type=%s, " 1665 "satisfy=CUPSD_AUTH_SATISFY_%s, num_names=%d", 1666 levels[best->level], types[type], 1667 best->satisfy ? "ANY" : "ALL", cupsArrayCount(best->names)); 1668 1669 if (best->limit == CUPSD_AUTH_LIMIT_IPP) 1670 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: op=%x(%s)", 1671 best->op, ippOpString(best->op)); 1672 1673 /* 1674 * Check host/ip-based accesses... 1675 */ 1676 1677#ifdef AF_INET6 1678 if (httpAddrFamily(hostaddr) == AF_INET6) 1679 { 1680 /* 1681 * Copy IPv6 address... 1682 */ 1683 1684 address[0] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[0]); 1685 address[1] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[1]); 1686 address[2] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[2]); 1687 address[3] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[3]); 1688 } 1689 else 1690#endif /* AF_INET6 */ 1691 if (con->http->hostaddr->addr.sa_family == AF_INET) 1692 { 1693 /* 1694 * Copy IPv4 address... 1695 */ 1696 1697 address[0] = 0; 1698 address[1] = 0; 1699 address[2] = 0; 1700 address[3] = ntohl(hostaddr->ipv4.sin_addr.s_addr); 1701 } 1702 else 1703 memset(address, 0, sizeof(address)); 1704 1705 hostlen = strlen(hostname); 1706 1707 auth = cupsdCheckAccess(address, hostname, hostlen, best) 1708 ? CUPSD_AUTH_ALLOW : CUPSD_AUTH_DENY; 1709 1710 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: auth=CUPSD_AUTH_%s...", 1711 auth ? "DENY" : "ALLOW"); 1712 1713 if (auth == CUPSD_AUTH_DENY && best->satisfy == CUPSD_AUTH_SATISFY_ALL) 1714 return (HTTP_FORBIDDEN); 1715 1716#ifdef HAVE_SSL 1717 /* 1718 * See if encryption is required... 1719 */ 1720 1721 if ((best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http->tls && 1722 _cups_strcasecmp(hostname, "localhost") && 1723 !httpAddrLocalhost(hostaddr) && 1724 best->satisfy == CUPSD_AUTH_SATISFY_ALL) && 1725 !(type == CUPSD_AUTH_NEGOTIATE || 1726 (type == CUPSD_AUTH_NONE && 1727 cupsdDefaultAuthType() == CUPSD_AUTH_NEGOTIATE))) 1728 { 1729 cupsdLogMessage(CUPSD_LOG_DEBUG, 1730 "cupsdIsAuthorized: Need upgrade to TLS..."); 1731 return (HTTP_UPGRADE_REQUIRED); 1732 } 1733#endif /* HAVE_SSL */ 1734 1735 /* 1736 * Now see what access level is required... 1737 */ 1738 1739 if (best->level == CUPSD_AUTH_ANON || /* Anonymous access - allow it */ 1740 (type == CUPSD_AUTH_NONE && cupsArrayCount(best->names) == 0)) 1741 return (HTTP_OK); 1742 1743 if (!con->username[0] && type == CUPSD_AUTH_NONE && 1744 best->limit == CUPSD_AUTH_LIMIT_IPP) 1745 { 1746 /* 1747 * Check for unauthenticated username... 1748 */ 1749 1750 ipp_attribute_t *attr; /* requesting-user-name attribute */ 1751 1752 1753 attr = ippFindAttribute(con->request, "requesting-user-name", IPP_TAG_NAME); 1754 if (attr) 1755 { 1756 cupsdLogMessage(CUPSD_LOG_DEBUG, 1757 "cupsdIsAuthorized: requesting-user-name=\"%s\"", 1758 attr->values[0].string.text); 1759 strlcpy(username, attr->values[0].string.text, sizeof(username)); 1760 } 1761 else if (best->satisfy == CUPSD_AUTH_SATISFY_ALL || auth == CUPSD_AUTH_DENY) 1762 return (HTTP_UNAUTHORIZED); /* Non-anonymous needs user/pass */ 1763 else 1764 return (HTTP_OK); /* unless overridden with Satisfy */ 1765 } 1766 else 1767 { 1768 cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdIsAuthorized: username=\"%s\"", 1769 con->username); 1770 1771#ifdef HAVE_AUTHORIZATION_H 1772 if (!con->username[0] && !con->authref) 1773#else 1774 if (!con->username[0]) 1775#endif /* HAVE_AUTHORIZATION_H */ 1776 { 1777 if (best->satisfy == CUPSD_AUTH_SATISFY_ALL || auth == CUPSD_AUTH_DENY) 1778 return (HTTP_UNAUTHORIZED); /* Non-anonymous needs user/pass */ 1779 else 1780 return (HTTP_OK); /* unless overridden with Satisfy */ 1781 } 1782 1783 1784 if (con->type != type && type != CUPSD_AUTH_NONE && 1785#ifdef HAVE_GSSAPI 1786 (type != CUPSD_AUTH_NEGOTIATE || con->gss_uid <= 0) && 1787#endif /* HAVE_GSSAPI */ 1788 con->type != CUPSD_AUTH_BASIC) 1789 { 1790 cupsdLogMessage(CUPSD_LOG_ERROR, "Authorized using %s, expected %s.", 1791 types[con->type], types[type]); 1792 1793 return (HTTP_UNAUTHORIZED); 1794 } 1795 1796 strlcpy(username, con->username, sizeof(username)); 1797 } 1798 1799 /* 1800 * OK, got a username. See if we need normal user access, or group 1801 * access... (root always matches) 1802 */ 1803 1804 if (!strcmp(username, "root")) 1805 return (HTTP_OK); 1806 1807 /* 1808 * Strip any @domain or @KDC from the username and owner... 1809 */ 1810 1811 if ((ptr = strchr(username, '@')) != NULL) 1812 *ptr = '\0'; 1813 1814 if (owner) 1815 { 1816 strlcpy(ownername, owner, sizeof(ownername)); 1817 1818 if ((ptr = strchr(ownername, '@')) != NULL) 1819 *ptr = '\0'; 1820 } 1821 else 1822 ownername[0] = '\0'; 1823 1824 /* 1825 * Get the user info... 1826 */ 1827 1828 if (username[0]) 1829 { 1830 pw = getpwnam(username); 1831 endpwent(); 1832 } 1833 else 1834 pw = NULL; 1835 1836 if (best->level == CUPSD_AUTH_USER) 1837 { 1838 /* 1839 * If there are no names associated with this location, then 1840 * any valid user is OK... 1841 */ 1842 1843 if (cupsArrayCount(best->names) == 0) 1844 return (HTTP_OK); 1845 1846 /* 1847 * Otherwise check the user list and return OK if this user is 1848 * allowed... 1849 */ 1850 1851 cupsdLogMessage(CUPSD_LOG_DEBUG2, 1852 "cupsdIsAuthorized: Checking user membership..."); 1853 1854#ifdef HAVE_AUTHORIZATION_H 1855 /* 1856 * If an authorization reference was supplied it must match a right name... 1857 */ 1858 1859 if (con->authref) 1860 { 1861 for (name = (char *)cupsArrayFirst(best->names); 1862 name; 1863 name = (char *)cupsArrayNext(best->names)) 1864 { 1865 if (!_cups_strncasecmp(name, "@AUTHKEY(", 9) && check_authref(con, name + 9)) 1866 return (HTTP_OK); 1867 else if (!_cups_strcasecmp(name, "@SYSTEM") && SystemGroupAuthKey && 1868 check_authref(con, SystemGroupAuthKey)) 1869 return (HTTP_OK); 1870 } 1871 1872 return (HTTP_FORBIDDEN); 1873 } 1874#endif /* HAVE_AUTHORIZATION_H */ 1875 1876 for (name = (char *)cupsArrayFirst(best->names); 1877 name; 1878 name = (char *)cupsArrayNext(best->names)) 1879 { 1880 if (!_cups_strcasecmp(name, "@OWNER") && owner && 1881 !_cups_strcasecmp(username, ownername)) 1882 return (HTTP_OK); 1883 else if (!_cups_strcasecmp(name, "@SYSTEM")) 1884 { 1885 for (i = 0; i < NumSystemGroups; i ++) 1886 if (cupsdCheckGroup(username, pw, SystemGroups[i])) 1887 return (HTTP_OK); 1888 } 1889 else if (name[0] == '@') 1890 { 1891 if (cupsdCheckGroup(username, pw, name + 1)) 1892 return (HTTP_OK); 1893 } 1894 else if (!_cups_strcasecmp(username, name)) 1895 return (HTTP_OK); 1896 } 1897 1898 return (con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED); 1899 } 1900 1901 /* 1902 * Check to see if this user is in any of the named groups... 1903 */ 1904 1905 cupsdLogMessage(CUPSD_LOG_DEBUG2, 1906 "cupsdIsAuthorized: Checking group membership..."); 1907 1908 /* 1909 * Check to see if this user is in any of the named groups... 1910 */ 1911 1912 for (name = (char *)cupsArrayFirst(best->names); 1913 name; 1914 name = (char *)cupsArrayNext(best->names)) 1915 { 1916 cupsdLogMessage(CUPSD_LOG_DEBUG2, 1917 "cupsdIsAuthorized: Checking group \"%s\" membership...", 1918 name); 1919 1920 if (!_cups_strcasecmp(name, "@SYSTEM")) 1921 { 1922 for (i = 0; i < NumSystemGroups; i ++) 1923 if (cupsdCheckGroup(username, pw, SystemGroups[i])) 1924 return (HTTP_OK); 1925 } 1926 else if (cupsdCheckGroup(username, pw, name)) 1927 return (HTTP_OK); 1928 } 1929 1930 /* 1931 * The user isn't part of the specified group, so deny access... 1932 */ 1933 1934 cupsdLogMessage(CUPSD_LOG_DEBUG, 1935 "cupsdIsAuthorized: User not in group(s)!"); 1936 1937 return (con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED); 1938} 1939 1940 1941/* 1942 * 'cupsdNewLocation()' - Create a new location for authorization. 1943 * 1944 * Note: Still need to call cupsdAddLocation() to add it to the list of global 1945 * locations. 1946 */ 1947 1948cupsd_location_t * /* O - Pointer to new location record */ 1949cupsdNewLocation(const char *location) /* I - Location path */ 1950{ 1951 cupsd_location_t *temp; /* New location */ 1952 1953 1954 /* 1955 * Try to allocate memory for the new location. 1956 */ 1957 1958 if ((temp = calloc(1, sizeof(cupsd_location_t))) == NULL) 1959 return (NULL); 1960 1961 /* 1962 * Initialize the record and copy the name over... 1963 */ 1964 1965 if ((temp->location = _cupsStrAlloc(location)) == NULL) 1966 { 1967 free(temp); 1968 return (NULL); 1969 } 1970 1971 temp->length = strlen(temp->location); 1972 1973 /* 1974 * Return the new record... 1975 */ 1976 1977 return (temp); 1978} 1979 1980 1981#ifdef HAVE_AUTHORIZATION_H 1982/* 1983 * 'check_authref()' - Check if an authorization services reference has the 1984 * supplied right. 1985 */ 1986 1987static int /* O - 1 if right is valid, 0 otherwise */ 1988check_authref(cupsd_client_t *con, /* I - Connection */ 1989 const char *right) /* I - Right name */ 1990{ 1991 OSStatus status; /* OS Status */ 1992 AuthorizationItem authright; /* Authorization right */ 1993 AuthorizationRights authrights; /* Authorization rights */ 1994 AuthorizationFlags authflags; /* Authorization flags */ 1995 1996 1997 /* 1998 * Check to see if the user is allowed to perform the task... 1999 */ 2000 2001 if (!con->authref) 2002 return (0); 2003 2004 authright.name = right; 2005 authright.valueLength = 0; 2006 authright.value = NULL; 2007 authright.flags = 0; 2008 2009 authrights.count = 1; 2010 authrights.items = &authright; 2011 2012 authflags = kAuthorizationFlagDefaults | 2013 kAuthorizationFlagExtendRights; 2014 2015 if ((status = AuthorizationCopyRights(con->authref, &authrights, 2016 kAuthorizationEmptyEnvironment, 2017 authflags, NULL)) != 0) 2018 { 2019 cupsdLogMessage(CUPSD_LOG_ERROR, 2020 "AuthorizationCopyRights(\"%s\") returned %d (%s)", 2021 authright.name, (int)status, cssmErrorString(status)); 2022 return (0); 2023 } 2024 2025 cupsdLogMessage(CUPSD_LOG_DEBUG2, 2026 "AuthorizationCopyRights(\"%s\") succeeded!", 2027 authright.name); 2028 2029 return (1); 2030} 2031#endif /* HAVE_AUTHORIZATION_H */ 2032 2033 2034/* 2035 * 'compare_locations()' - Compare two locations. 2036 */ 2037 2038static int /* O - Result of comparison */ 2039compare_locations(cupsd_location_t *a, /* I - First location */ 2040 cupsd_location_t *b) /* I - Second location */ 2041{ 2042 return (strcmp(b->location, a->location)); 2043} 2044 2045 2046/* 2047 * 'copy_authmask()' - Copy function for auth masks. 2048 */ 2049 2050static cupsd_authmask_t * /* O - New auth mask */ 2051copy_authmask(cupsd_authmask_t *mask, /* I - Existing auth mask */ 2052 void *data) /* I - User data (unused) */ 2053{ 2054 cupsd_authmask_t *temp; /* New auth mask */ 2055 2056 2057 (void)data; 2058 2059 if ((temp = malloc(sizeof(cupsd_authmask_t))) != NULL) 2060 { 2061 memcpy(temp, mask, sizeof(cupsd_authmask_t)); 2062 2063 if (temp->type == CUPSD_AUTH_NAME || temp->type == CUPSD_AUTH_INTERFACE) 2064 { 2065 /* 2066 * Make a copy of the name... 2067 */ 2068 2069 if ((temp->mask.name.name = _cupsStrAlloc(temp->mask.name.name)) == NULL) 2070 { 2071 /* 2072 * Failed to make copy... 2073 */ 2074 2075 free(temp); 2076 temp = NULL; 2077 } 2078 } 2079 } 2080 2081 return (temp); 2082} 2083 2084 2085#if !HAVE_LIBPAM 2086/* 2087 * 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms, 2088 * as needed. 2089 */ 2090 2091static char * /* O - Encrypted password */ 2092cups_crypt(const char *pw, /* I - Password string */ 2093 const char *salt) /* I - Salt (key) string */ 2094{ 2095 if (!strncmp(salt, "$1$", 3)) 2096 { 2097 /* 2098 * Use MD5 passwords without the benefit of PAM; this is for 2099 * Slackware Linux, and the algorithm was taken from the 2100 * old shadow-19990827/lib/md5crypt.c source code... :( 2101 */ 2102 2103 int i; /* Looping var */ 2104 unsigned long n; /* Output number */ 2105 int pwlen; /* Length of password string */ 2106 const char *salt_end; /* End of "salt" data for MD5 */ 2107 char *ptr; /* Pointer into result string */ 2108 _cups_md5_state_t state; /* Primary MD5 state info */ 2109 _cups_md5_state_t state2; /* Secondary MD5 state info */ 2110 unsigned char digest[16]; /* MD5 digest result */ 2111 static char result[120]; /* Final password string */ 2112 2113 2114 /* 2115 * Get the salt data between dollar signs, e.g. $1$saltdata$md5. 2116 * Get a maximum of 8 characters of salt data after $1$... 2117 */ 2118 2119 for (salt_end = salt + 3; *salt_end && (salt_end - salt) < 11; salt_end ++) 2120 if (*salt_end == '$') 2121 break; 2122 2123 /* 2124 * Compute the MD5 sum we need... 2125 */ 2126 2127 pwlen = strlen(pw); 2128 2129 _cupsMD5Init(&state); 2130 _cupsMD5Append(&state, (unsigned char *)pw, pwlen); 2131 _cupsMD5Append(&state, (unsigned char *)salt, salt_end - salt); 2132 2133 _cupsMD5Init(&state2); 2134 _cupsMD5Append(&state2, (unsigned char *)pw, pwlen); 2135 _cupsMD5Append(&state2, (unsigned char *)salt + 3, salt_end - salt - 3); 2136 _cupsMD5Append(&state2, (unsigned char *)pw, pwlen); 2137 _cupsMD5Finish(&state2, digest); 2138 2139 for (i = pwlen; i > 0; i -= 16) 2140 _cupsMD5Append(&state, digest, i > 16 ? 16 : i); 2141 2142 for (i = pwlen; i > 0; i >>= 1) 2143 _cupsMD5Append(&state, (unsigned char *)((i & 1) ? "" : pw), 1); 2144 2145 _cupsMD5Finish(&state, digest); 2146 2147 for (i = 0; i < 1000; i ++) 2148 { 2149 _cupsMD5Init(&state); 2150 2151 if (i & 1) 2152 _cupsMD5Append(&state, (unsigned char *)pw, pwlen); 2153 else 2154 _cupsMD5Append(&state, digest, 16); 2155 2156 if (i % 3) 2157 _cupsMD5Append(&state, (unsigned char *)salt + 3, salt_end - salt - 3); 2158 2159 if (i % 7) 2160 _cupsMD5Append(&state, (unsigned char *)pw, pwlen); 2161 2162 if (i & 1) 2163 _cupsMD5Append(&state, digest, 16); 2164 else 2165 _cupsMD5Append(&state, (unsigned char *)pw, pwlen); 2166 2167 _cupsMD5Finish(&state, digest); 2168 } 2169 2170 /* 2171 * Copy the final sum to the result string and return... 2172 */ 2173 2174 memcpy(result, salt, (size_t)(salt_end - salt)); 2175 ptr = result + (salt_end - salt); 2176 *ptr++ = '$'; 2177 2178 for (i = 0; i < 5; i ++, ptr += 4) 2179 { 2180 n = ((((unsigned)digest[i] << 8) | (unsigned)digest[i + 6]) << 8); 2181 2182 if (i < 4) 2183 n |= (unsigned)digest[i + 12]; 2184 else 2185 n |= (unsigned)digest[5]; 2186 2187 to64(ptr, n, 4); 2188 } 2189 2190 to64(ptr, (unsigned)digest[11], 2); 2191 ptr += 2; 2192 *ptr = '\0'; 2193 2194 return (result); 2195 } 2196 else 2197 { 2198 /* 2199 * Use the standard crypt() function... 2200 */ 2201 2202 return (crypt(pw, salt)); 2203 } 2204} 2205#endif /* !HAVE_LIBPAM */ 2206 2207 2208/* 2209 * 'free_authmask()' - Free function for auth masks. 2210 */ 2211 2212static void 2213free_authmask(cupsd_authmask_t *mask, /* I - Auth mask to free */ 2214 void *data) /* I - User data (unused) */ 2215{ 2216 (void)data; 2217 2218 if (mask->type == CUPSD_AUTH_NAME || mask->type == CUPSD_AUTH_INTERFACE) 2219 _cupsStrFree(mask->mask.name.name); 2220 2221 free(mask); 2222} 2223 2224 2225#if HAVE_LIBPAM 2226/* 2227 * 'pam_func()' - PAM conversation function. 2228 */ 2229 2230static int /* O - Success or failure */ 2231pam_func( 2232 int num_msg, /* I - Number of messages */ 2233 const struct pam_message **msg, /* I - Messages */ 2234 struct pam_response **resp, /* O - Responses */ 2235 void *appdata_ptr) 2236 /* I - Pointer to connection */ 2237{ 2238 int i; /* Looping var */ 2239 struct pam_response *replies; /* Replies */ 2240 cupsd_authdata_t *data; /* Pointer to auth data */ 2241 2242 2243 /* 2244 * Allocate memory for the responses... 2245 */ 2246 2247 if ((replies = malloc(sizeof(struct pam_response) * (size_t)num_msg)) == NULL) 2248 return (PAM_CONV_ERR); 2249 2250 /* 2251 * Answer all of the messages... 2252 */ 2253 2254 DEBUG_printf(("pam_func: appdata_ptr = %p\n", appdata_ptr)); 2255 2256 data = (cupsd_authdata_t *)appdata_ptr; 2257 2258 for (i = 0; i < num_msg; i ++) 2259 { 2260 DEBUG_printf(("pam_func: Message = \"%s\"\n", msg[i]->msg)); 2261 2262 switch (msg[i]->msg_style) 2263 { 2264 case PAM_PROMPT_ECHO_ON: 2265 DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_ON, returning \"%s\"...\n", 2266 data->username)); 2267 replies[i].resp_retcode = PAM_SUCCESS; 2268 replies[i].resp = strdup(data->username); 2269 break; 2270 2271 case PAM_PROMPT_ECHO_OFF: 2272 DEBUG_printf(("pam_func: PAM_PROMPT_ECHO_OFF, returning \"%s\"...\n", 2273 data->password)); 2274 replies[i].resp_retcode = PAM_SUCCESS; 2275 replies[i].resp = strdup(data->password); 2276 break; 2277 2278 case PAM_TEXT_INFO: 2279 DEBUG_puts("pam_func: PAM_TEXT_INFO..."); 2280 replies[i].resp_retcode = PAM_SUCCESS; 2281 replies[i].resp = NULL; 2282 break; 2283 2284 case PAM_ERROR_MSG: 2285 DEBUG_puts("pam_func: PAM_ERROR_MSG..."); 2286 replies[i].resp_retcode = PAM_SUCCESS; 2287 replies[i].resp = NULL; 2288 break; 2289 2290 default: 2291 DEBUG_printf(("pam_func: Unknown PAM message %d...\n", 2292 msg[i]->msg_style)); 2293 free(replies); 2294 return (PAM_CONV_ERR); 2295 } 2296 } 2297 2298 /* 2299 * Return the responses back to PAM... 2300 */ 2301 2302 *resp = replies; 2303 2304 return (PAM_SUCCESS); 2305} 2306#else 2307 2308 2309/* 2310 * 'to64()' - Base64-encode an integer value... 2311 */ 2312 2313static void 2314to64(char *s, /* O - Output string */ 2315 unsigned long v, /* I - Value to encode */ 2316 int n) /* I - Number of digits */ 2317{ 2318 const char *itoa64 = "./0123456789" 2319 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 2320 "abcdefghijklmnopqrstuvwxyz"; 2321 2322 2323 for (; n > 0; n --, v >>= 6) 2324 *s++ = itoa64[v & 0x3f]; 2325} 2326#endif /* HAVE_LIBPAM */ 2327 2328 2329/* 2330 * End of "$Id: auth.c 12131 2014-08-28 23:38:16Z msweet $". 2331 */ 2332