-;/*
- * "$Id: auth.c 5043 2006-02-01 18:55:16Z mike $"
+/*
+ * "$Id: auth.c 5464 2006-04-26 01:34:14Z mike $"
*
* Authorization routines for the Common UNIX Printing System (CUPS).
*
* cupsdAddName() - Add a name to a location...
* cupsdAllowHost() - Add a host name that is allowed to access the
* location.
- * cupsdAllowIP() - Add an IP address or network that is allowed to
- * access the location.
+ * cupsdAllowIP() - Add an IP address or network that is allowed
+ * to access the location.
+ * cupsdAuthorize() - Validate any authorization credentials.
* cupsdCheckAuth() - Check authorization masks.
* cupsdCheckGroup() - Check for a user's group membership.
* cupsdCopyLocation() - Make a copy of a location...
- * cupsdDeleteAllLocations() - Free all memory used for location authorization.
+ * cupsdDeleteAllLocations() - Free all memory used for location
+ * authorization.
* cupsdDeleteLocation() - Free all memory used by a location.
- * cupsdDenyHost() - Add a host name that is not allowed to access the
- * location.
- * cupsdDenyIP() - Add an IP address or network that is not allowed
- * to access the location.
+ * cupsdDenyHost() - Add a host name that is not allowed to access
+ * the location.
+ * cupsdDenyIP() - Add an IP address or network that is not
+ * allowed to access the location.
* cupsdFindBest() - Find the location entry that best matches the
* resource.
* cupsdFindLocation() - Find the named location.
- * cupsdGetMD5Passwd() - Get an MD5 password.
* cupsdIsAuthorized() - Check to see if the user is authorized...
* add_allow() - Add an allow mask to the location.
* add_deny() - Add a deny mask to the location.
+ * compare_locations() - Compare two locations.
* cups_crypt() - Encrypt the password using the DES or MD5
* algorithms, as needed.
+ * get_md5_password() - Get an MD5 password.
* pam_func() - PAM conversation function.
* to64() - Base64-encode an integer value...
*/
#ifdef HAVE_USERSEC_H
# include <usersec.h>
#endif /* HAVE_USERSEC_H */
+#ifdef HAVE_MEMBERSHIP_H
+# include <membership.h>
+#endif /* HAVE_MEMBERSHIP_H */
/*
static cupsd_authmask_t *add_allow(cupsd_location_t *loc);
static cupsd_authmask_t *add_deny(cupsd_location_t *loc);
+static int compare_locations(cupsd_location_t *a,
+ cupsd_location_t *b);
#if !HAVE_LIBPAM
static char *cups_crypt(const char *pw, const char *salt);
#endif /* !HAVE_LIBPAM */
+static char *get_md5_password(const char *username,
+ const char *group, char passwd[33]);
#if HAVE_LIBPAM
static int pam_func(int, const struct pam_message **,
struct pam_response **, void *);
*/
#if defined(__hpux) && defined(HAVE_LIBPAM)
-static cupsd_authdata_t *auth_datat; /* Current client being authenticated */
+static cupsd_authdata_t *auth_data; /* Current client being authenticated */
#endif /* __hpux && HAVE_LIBPAM */
/*
- * Try to allocate memory for the new location.
+ * Make sure the locations array is created...
*/
- if (NumLocations == 0)
- temp = malloc(sizeof(cupsd_location_t));
- else
- temp = realloc(Locations, sizeof(cupsd_location_t) * (NumLocations + 1));
+ if (!Locations)
+ Locations = cupsArrayNew((cups_array_func_t)compare_locations, NULL);
- if (temp == NULL)
+ if (!Locations)
return (NULL);
- Locations = temp;
- temp += NumLocations;
- NumLocations ++;
+ /*
+ * Try to allocate memory for the new location.
+ */
+
+ if ((temp = calloc(1, sizeof(cupsd_location_t))) == NULL)
+ return (NULL);
/*
* Initialize the record and copy the name over...
*/
- memset(temp, 0, sizeof(cupsd_location_t));
- strlcpy(temp->location, location, sizeof(temp->location));
- temp->length = strlen(temp->location);
+ temp->location = strdup(location);
+ temp->length = strlen(temp->location);
+
+ cupsArrayAdd(Locations, temp);
- cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAddLocation: added location \'%s\'",
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddLocation: added location \'%s\'",
location);
/*
if (temp == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to add name to location %s: %s",
- loc->location, strerror(errno));
+ loc->location ? loc->location : "nil", strerror(errno));
return;
}
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to duplicate name for location %s: %s",
- loc->location, strerror(errno));
+ loc->location ? loc->location : "nil", strerror(errno));
return;
}
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAllowHost(loc=%p(%s), name=\"%s\")",
- loc, loc->location, name);
+ loc, loc->location ? loc->location : "nil", name);
if ((temp = add_allow(loc)) == NULL)
return;
- if (strcasecmp(name, "@LOCAL") == 0)
+ if (!strcasecmp(name, "@LOCAL"))
{
/*
* Allow *interface*...
temp->mask.name.name = strdup("*");
temp->mask.name.length = 1;
}
- else if (strncasecmp(name, "@IF(", 4) == 0)
+ else if (!strncasecmp(name, "@IF(", 4))
{
/*
* Allow *interface*...
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdAllowIP(loc=%p(%s), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)",
- loc, loc->location, address[0], address[1], address[2],
- address[3], netmask[0], netmask[1], netmask[2],
- netmask[3]);
+ loc, loc->location ? loc->location : "nil",
+ address[0], address[1], address[2], address[3],
+ netmask[0], netmask[1], netmask[2], netmask[3]);
if ((temp = add_allow(loc)) == NULL)
return;
*/
authorization += 5;
- while (isspace(*authorization))
+ while (isspace(*authorization & 255))
authorization ++;
if ((localuser = cupsdFindCert(authorization)) != NULL)
authorization += 5;
- while (isspace(*authorization))
+ while (isspace(*authorization & 255))
authorization ++;
userlen = sizeof(username);
strlcpy(data.username, username, sizeof(data.username));
strlcpy(data.password, password, sizeof(data.password));
+# ifdef __sun
+ pamdata.conv = (int (*)(int, struct pam_message **,
+ struct pam_response **,
+ void *))pam_func;
+# else
pamdata.conv = pam_func;
+# endif /* __sun */
pamdata.appdata_ptr = &data;
# ifdef __hpux
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdAuthorize: Unknown username \"%s\"!",
username);
- return (HTTP_UNAUTHORIZED);
+ return;
}
# ifdef HAVE_SHADOW_H
* Do Basic authentication with the Digest password file...
*/
- if (!cupsdGetMD5Passwd(username, NULL, md5))
+ if (!get_md5_password(username, NULL, md5))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdAuthorize: Unknown MD5 username \"%s\"!",
* Validate the username and password...
*/
- if (!cupsdGetMD5Passwd(username, NULL, md5))
+ if (!get_md5_password(username, NULL, md5))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdAuthorize: Unknown MD5 username \"%s\"!",
if (name_len >= masks->mask.name.length &&
masks->mask.name.name[0] == '.' &&
- strcasecmp(name + name_len - masks->mask.name.length,
- masks->mask.name.name) == 0)
+ !strcasecmp(name + name_len - masks->mask.name.length,
+ masks->mask.name.name))
return (1);
break;
int i; /* Looping var */
struct group *group; /* System group info */
char junk[33]; /* MD5 password (not used) */
+#ifdef HAVE_MBR_UID_TO_UUID
+ uuid_t useruuid, /* UUID for username */
+ groupuuid; /* UUID for groupname */
+ int is_member; /* True if user is a member of group */
+#endif /* HAVE_MBR_UID_TO_UUID */
cupsdLogMessage(CUPSD_LOG_DEBUG2,
if (user && group && group->gr_gid == user->pw_gid)
return (1);
+#ifdef HAVE_MBR_UID_TO_UUID
+ /*
+ * Check group membership through MacOS X membership API...
+ */
+
+ if (user && group)
+ if (!mbr_uid_to_uuid(user->pw_uid, useruuid))
+ if (!mbr_gid_to_uuid(group->gr_gid, groupuuid))
+ if (!mbr_check_membership(useruuid, groupuuid, &is_member))
+ if (is_member)
+ return (1);
+#endif /* HAVE_MBR_UID_TO_UUID */
+
/*
* Username not found, group not found, or user is not part of the
* system group... Check for a user and group in the MD5 password
* file...
*/
- if (cupsdGetMD5Passwd(username, groupname, junk) != NULL)
+ if (get_md5_password(username, groupname, junk) != NULL)
return (1);
/*
cupsd_location_t **loc) /* IO - Original location */
{
int i; /* Looping var */
- int locindex; /* Index into Locations array */
cupsd_location_t *temp; /* New location */
char location[HTTP_MAX_URI];
/* Location of resource */
- /*
- * Add the new location, updating the original location
- * pointer as needed...
- */
-
- locindex = *loc - Locations;
-
/*
* Use a local copy of location because cupsdAddLocation may cause
* this memory to be moved...
if ((temp = cupsdAddLocation(location)) == NULL)
return (NULL);
- *loc = Locations + locindex;
-
/*
* Copy the information from the original location to the new one.
*/
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdCopyLocation: Unable to allocate memory for %d names: %s",
temp->num_names, strerror(errno));
- NumLocations --;
+
+ cupsdDeleteLocation(temp);
return (NULL);
}
"cupsdCopyLocation: Unable to copy name \"%s\": %s",
(*loc)->names[i], strerror(errno));
- NumLocations --;
+ cupsdDeleteLocation(temp);
return (NULL);
}
}
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdCopyLocation: Unable to allocate memory for %d allow rules: %s",
temp->num_allow, strerror(errno));
- NumLocations --;
+ cupsdDeleteLocation(temp);
return (NULL);
}
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdCopyLocation: Unable to copy allow name \"%s\": %s",
(*loc)->allow[i].mask.name.name, strerror(errno));
- NumLocations --;
+ cupsdDeleteLocation(temp);
return (NULL);
}
break;
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdCopyLocation: Unable to allocate memory for %d deny rules: %s",
temp->num_deny, strerror(errno));
- NumLocations --;
+ cupsdDeleteLocation(temp);
return (NULL);
}
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdCopyLocation: Unable to copy deny name \"%s\": %s",
(*loc)->deny[i].mask.name.name, strerror(errno));
- NumLocations --;
+ cupsdDeleteLocation(temp);
return (NULL);
}
break;
void
cupsdDeleteAllLocations(void)
{
- int i; /* Looping var */
cupsd_location_t *loc; /* Current location */
* Free all of the allow/deny records first...
*/
- for (i = NumLocations, loc = Locations; i > 0; i --, loc ++)
+ for (loc = (cupsd_location_t *)cupsArrayFirst(Locations);
+ loc;
+ loc = (cupsd_location_t *)cupsArrayNext(Locations))
cupsdDeleteLocation(loc);
/*
* Then free the location array...
*/
- if (NumLocations > 0)
- free(Locations);
-
- Locations = NULL;
- NumLocations = 0;
+ cupsArrayDelete(Locations);
+ Locations = NULL;
}
cupsd_authmask_t *mask; /* Current mask */
+ cupsArrayRemove(Locations, loc);
+
for (i = loc->num_names - 1; i >= 0; i --)
free(loc->names[i]);
if (loc->num_deny > 0)
free(loc->deny);
+
+ free(loc->location);
+ free(loc);
}
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDenyHost(loc=%p(%s), name=\"%s\")",
- loc, loc->location, name);
+ loc, loc->location ? loc->location : "nil", name);
if ((temp = add_deny(loc)) == NULL)
return;
- if (strcasecmp(name, "@LOCAL") == 0)
+ if (!strcasecmp(name, "@LOCAL"))
{
/*
* Deny *interface*...
temp->mask.name.name = strdup("*");
temp->mask.name.length = 1;
}
- else if (strncasecmp(name, "@IF(", 4) == 0)
+ else if (!strncasecmp(name, "@IF(", 4))
{
/*
* Deny *interface*...
cupsdLogMessage(CUPSD_LOG_DEBUG,
"cupsdDenyIP(loc=%p(%s), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)",
- loc, loc->location, address[0], address[1], address[2],
- address[3], netmask[0], netmask[1], netmask[2],
- netmask[3]);
+ loc, loc->location ? loc->location : "nil",
+ address[0], address[1], address[2], address[3],
+ netmask[0], netmask[1], netmask[2], netmask[3]);
if ((temp = add_deny(loc)) == NULL)
return;
cupsdFindBest(const char *path, /* I - Resource path */
http_state_t state) /* I - HTTP state/request */
{
- int i; /* Looping var */
char uri[HTTP_MAX_URI],
/* URI in request... */
*uriptr; /* Pointer into URI */
best = NULL;
bestlen = 0;
- for (i = NumLocations, loc = Locations; i > 0; i --, loc ++)
+ for (loc = (cupsd_location_t *)cupsArrayFirst(Locations);
+ loc;
+ loc = (cupsd_location_t *)cupsArrayNext(Locations))
{
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: Location %s Limit %x",
- loc->location, loc->limit);
+ loc->location ? loc->location : "nil", loc->limit);
if (!strncmp(uri, "/printers/", 10) || !strncmp(uri, "/classes/", 9))
{
* Use case-insensitive comparison for queue names...
*/
- if (loc->length > bestlen &&
- strncasecmp(uri, loc->location, loc->length) == 0 &&
+ if (loc->length > bestlen && loc->location &&
+ !strncasecmp(uri, loc->location, loc->length) &&
loc->location[0] == '/' &&
(limit & loc->limit) != 0)
{
* Use case-sensitive comparison for other URIs...
*/
- if (loc->length > bestlen &&
+ if (loc->length > bestlen && loc->location &&
!strncmp(uri, loc->location, loc->length) &&
loc->location[0] == '/' &&
(limit & loc->limit) != 0)
cupsd_location_t * /* O - Location that matches */
cupsdFindLocation(const char *location) /* I - Connection */
{
- int i; /* Looping var */
-
-
- /*
- * Loop through the list of locations to find a match...
- */
-
- for (i = 0; i < NumLocations; i ++)
- if (!strcasecmp(Locations[i].location, location))
- return (Locations + i);
-
- return (NULL);
-}
-
-
-/*
- * 'cupsdGetMD5Passwd()' - Get an MD5 password.
- */
-
-char * /* O - MD5 password string */
-cupsdGetMD5Passwd(const char *username, /* I - Username */
- const char *group, /* I - Group */
- char passwd[33])/* O - MD5 password string */
-{
- cups_file_t *fp; /* passwd.md5 file */
- char filename[1024], /* passwd.md5 filename */
- line[256], /* Line from file */
- tempuser[33], /* User from file */
- tempgroup[33]; /* Group from file */
-
-
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdGetMD5Passwd(username=\"%s\", group=\"%s\", passwd=%p)",
- username, group ? group : "(null)", passwd);
-
- snprintf(filename, sizeof(filename), "%s/passwd.md5", ServerRoot);
- if ((fp = cupsFileOpen(filename, "r")) == NULL)
- {
- if (errno != ENOENT)
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open %s - %s", filename,
- strerror(errno));
-
- return (NULL);
- }
-
- while (cupsFileGets(fp, line, sizeof(line)) != NULL)
- {
- if (sscanf(line, "%32[^:]:%32[^:]:%32s", tempuser, tempgroup, passwd) != 3)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad MD5 password line: %s", line);
- continue;
- }
-
- if (strcmp(username, tempuser) == 0 &&
- (group == NULL || strcmp(group, tempgroup) == 0))
- {
- /*
- * Found the password entry!
- */
+ cupsd_location_t key; /* Search key */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "Found MD5 user %s, group %s...",
- username, tempgroup);
- cupsFileClose(fp);
- return (passwd);
- }
- }
+ key.location = (char *)location;
- /*
- * Didn't find a password entry - return NULL!
- */
-
- cupsFileClose(fp);
- return (NULL);
+ return ((cupsd_location_t *)cupsArrayFind(Locations, &key));
}
best = con->best;
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdIsAuthorized: level=AUTH_%s, type=AUTH_%s, satisfy=AUTH_SATISFY_%s, num_names=%d",
+ "cupsdIsAuthorized: level=AUTH_%s, type=AUTH_%s, "
+ "satisfy=AUTH_SATISFY_%s, num_names=%d",
levels[best->level], types[best->type],
best->satisfy ? "ANY" : "ALL", best->num_names);
if (!strcasecmp(con->http.hostname, "localhost"))
{
/*
- * Access from localhost (127.0.0.1 or :::1) is always allowed...
+ * Access from localhost (127.0.0.1 or ::1) is always allowed...
*/
auth = AUTH_ALLOW;
* See if encryption is required...
*/
- if (best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls)
+ if (best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls &&
+ strcasecmp(con->http.hostname, "localhost") &&
+ best->satisfy == AUTH_SATISFY_ALL)
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdIsAuthorized: Need upgrade to TLS...");
}
+/*
+ * 'compare_locations()' - Compare two locations.
+ */
+
+static int /* O - Result of comparison */
+compare_locations(cupsd_location_t *a, /* I - First location */
+ cupsd_location_t *b) /* I - Second location */
+{
+ return (strcmp(b->location, a->location));
+}
+
+
#if !HAVE_LIBPAM
/*
* 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms,
cups_crypt(const char *pw, /* I - Password string */
const char *salt) /* I - Salt (key) string */
{
- if (strncmp(salt, "$1$", 3) == 0)
+ if (!strncmp(salt, "$1$", 3))
{
/*
* Use MD5 passwords without the benefit of PAM; this is for
pwlen = strlen(pw);
- _cups_md5_init(&state);
- _cups_md5_append(&state, (unsigned char *)pw, pwlen);
- _cups_md5_append(&state, (unsigned char *)salt, salt_end - salt);
+ _cupsMD5Init(&state);
+ _cupsMD5Append(&state, (unsigned char *)pw, pwlen);
+ _cupsMD5Append(&state, (unsigned char *)salt, salt_end - salt);
- _cups_md5_init(&state2);
- _cups_md5_append(&state2, (unsigned char *)pw, pwlen);
- _cups_md5_append(&state2, (unsigned char *)salt + 3, salt_end - salt - 3);
- _cups_md5_append(&state2, (unsigned char *)pw, pwlen);
- _cups_md5_finish(&state2, digest);
+ _cupsMD5Init(&state2);
+ _cupsMD5Append(&state2, (unsigned char *)pw, pwlen);
+ _cupsMD5Append(&state2, (unsigned char *)salt + 3, salt_end - salt - 3);
+ _cupsMD5Append(&state2, (unsigned char *)pw, pwlen);
+ _cupsMD5Finish(&state2, digest);
for (i = pwlen; i > 0; i -= 16)
- _cups_md5_append(&state, digest, i > 16 ? 16 : i);
+ _cupsMD5Append(&state, digest, i > 16 ? 16 : i);
for (i = pwlen; i > 0; i >>= 1)
- _cups_md5_append(&state, (unsigned char *)((i & 1) ? "" : pw), 1);
+ _cupsMD5Append(&state, (unsigned char *)((i & 1) ? "" : pw), 1);
- _cups_md5_finish(&state, digest);
+ _cupsMD5Finish(&state, digest);
for (i = 0; i < 1000; i ++)
{
- _cups_md5_init(&state);
+ _cupsMD5Init(&state);
if (i & 1)
- _cups_md5_append(&state, (unsigned char *)pw, pwlen);
+ _cupsMD5Append(&state, (unsigned char *)pw, pwlen);
else
- _cups_md5_append(&state, digest, 16);
+ _cupsMD5Append(&state, digest, 16);
if (i % 3)
- _cups_md5_append(&state, (unsigned char *)salt + 3, salt_end - salt - 3);
+ _cupsMD5Append(&state, (unsigned char *)salt + 3, salt_end - salt - 3);
if (i % 7)
- _cups_md5_append(&state, (unsigned char *)pw, pwlen);
+ _cupsMD5Append(&state, (unsigned char *)pw, pwlen);
if (i & 1)
- _cups_md5_append(&state, digest, 16);
+ _cupsMD5Append(&state, digest, 16);
else
- _cups_md5_append(&state, (unsigned char *)pw, pwlen);
+ _cupsMD5Append(&state, (unsigned char *)pw, pwlen);
- _cups_md5_finish(&state, digest);
+ _cupsMD5Finish(&state, digest);
}
/*
#endif /* !HAVE_LIBPAM */
+/*
+ * 'get_md5_password()' - Get an MD5 password.
+ */
+
+static char * /* O - MD5 password string */
+get_md5_password(const char *username, /* I - Username */
+ const char *group, /* I - Group */
+ char passwd[33]) /* O - MD5 password string */
+{
+ cups_file_t *fp; /* passwd.md5 file */
+ char filename[1024], /* passwd.md5 filename */
+ line[256], /* Line from file */
+ tempuser[33], /* User from file */
+ tempgroup[33]; /* Group from file */
+
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "get_md5_password(username=\"%s\", group=\"%s\", passwd=%p)",
+ username, group ? group : "(null)", passwd);
+
+ snprintf(filename, sizeof(filename), "%s/passwd.md5", ServerRoot);
+ if ((fp = cupsFileOpen(filename, "r")) == NULL)
+ {
+ if (errno != ENOENT)
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open %s - %s", filename,
+ strerror(errno));
+
+ return (NULL);
+ }
+
+ while (cupsFileGets(fp, line, sizeof(line)) != NULL)
+ {
+ if (sscanf(line, "%32[^:]:%32[^:]:%32s", tempuser, tempgroup, passwd) != 3)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad MD5 password line: %s", line);
+ continue;
+ }
+
+ if (!strcmp(username, tempuser) &&
+ (group == NULL || !strcmp(group, tempgroup)))
+ {
+ /*
+ * Found the password entry!
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "Found MD5 user %s, group %s...",
+ username, tempgroup);
+
+ cupsFileClose(fp);
+ return (passwd);
+ }
+ }
+
+ /*
+ * Didn't find a password entry - return NULL!
+ */
+
+ cupsFileClose(fp);
+ return (NULL);
+}
+
+
#if HAVE_LIBPAM
/*
* 'pam_func()' - PAM conversation function.
/*
- * End of "$Id: auth.c 5043 2006-02-01 18:55:16Z mike $".
+ * End of "$Id: auth.c 5464 2006-04-26 01:34:14Z mike $".
*/