diff --git a/cups/cups.h b/cups/cups.h index 8f5c818..9d8c3a3 100644 --- a/cups/cups.h +++ b/cups/cups.h @@ -606,6 +606,9 @@ extern ssize_t cupsHashData(const char *algorithm, const void *data, size_t dat extern int cupsAddIntegerOption(const char *name, int value, int num_options, cups_option_t **options) _CUPS_API_2_2_4; extern int cupsGetIntegerOption(const char *name, int num_options, cups_option_t *options) _CUPS_API_2_2_4; +/* New in CUPS 2.3 */ +extern const char *cupsHashString(const unsigned char *hash, size_t hashsize, char *buffer, size_t bufsize); + # ifdef __cplusplus } # endif /* __cplusplus */ diff --git a/cups/hash.c b/cups/hash.c index ede5461..8ebe20b 100644 --- a/cups/hash.c +++ b/cups/hash.c @@ -21,6 +21,8 @@ # include #elif defined(HAVE_GNUTLS) # include +#else +# include "md5-private.h" #endif /* __APPLE__ */ @@ -171,7 +173,9 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ unsigned char temp[64]; /* Temporary hash buffer */ size_t tempsize = 0; /* Truncate to this size? */ - if (!strcmp(algorithm, "sha")) + if (!strcmp(algorithm, "md5")) + alg = GNUTLS_DIG_MD5; + else if (!strcmp(algorithm, "sha")) alg = GNUTLS_DIG_SHA1; else if (!strcmp(algorithm, "sha2-224")) alg = GNUTLS_DIG_SHA224; @@ -219,10 +223,20 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ #else /* - * No hash support without CommonCrypto or GNU TLS... + * No hash support beyond MD5 without CommonCrypto or GNU TLS... */ - if (hashsize < 64) + if (!strcmp(algorithm, "md5")) + { + _cups_md5_state_t state; /* MD5 state info */ + + _cupsMD5Init(&state); + _cupsMD5Append(&state, data, datalen); + _cupsMD5Finish(&state, hash); + + return (16); + } + else if (hashsize < 64) goto too_small; #endif /* __APPLE__ */ @@ -243,3 +257,51 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1); return (-1); } + + +/* + * 'cupsHashString()' - Format a hash value as a hexadecimal string. + * + * The passed buffer must be at least 2 * hashsize + 1 characters in length. + */ + +const char * /* O - Formatted string */ +cupsHashString( + const unsigned char *hash, /* I - Hash */ + size_t hashsize, /* I - Size of hash */ + char *buffer, /* I - String buffer */ + size_t bufsize) /* I - Size of string buffer */ +{ + char *bufptr = buffer; /* Pointer into buffer */ + static const char *hex = "0123456789abcdef"; + /* Hex characters (lowercase!) */ + + + /* + * Range check input... + */ + + if (!hash || hashsize < 1 || !buffer || bufsize < (2 * hashsize + 1)) + { + if (buffer) + *buffer = '\0'; + return (NULL); + } + + /* + * Loop until we've converted the whole hash... + */ + + while (hashsize > 0) + { + *bufptr++ = hex[*hash >> 4]; + *bufptr++ = hex[*hash & 15]; + + hash ++; + hashsize --; + } + + *bufptr = '\0'; + + return (buffer); +} diff --git a/cups/md5passwd.c b/cups/md5passwd.c index a9817aa..c9ffe04 100644 --- a/cups/md5passwd.c +++ b/cups/md5passwd.c @@ -17,6 +17,7 @@ * Include necessary headers... */ +#include #include "http-private.h" #include "string-private.h" @@ -31,7 +32,6 @@ httpMD5(const char *username, /* I - User name */ const char *passwd, /* I - Password string */ char md5[33]) /* O - MD5 string */ { - _cups_md5_state_t state; /* MD5 state info */ unsigned char sum[16]; /* Sum data */ char line[256]; /* Line to sum */ @@ -41,15 +41,13 @@ httpMD5(const char *username, /* I - User name */ */ snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd); - _cupsMD5Init(&state); - _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); - _cupsMD5Finish(&state, sum); + cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); /* * Return the sum... */ - return (httpMD5String(sum, md5)); + return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); } @@ -65,7 +63,6 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ const char *resource, /* I - Resource path */ char md5[33]) /* IO - MD5 sum */ { - _cups_md5_state_t state; /* MD5 state info */ unsigned char sum[16]; /* Sum data */ char line[1024]; /* Line of data */ char a2[33]; /* Hash of method and resource */ @@ -76,9 +73,7 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ */ snprintf(line, sizeof(line), "%s:%s", method, resource); - _cupsMD5Init(&state); - _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); - _cupsMD5Finish(&state, sum); + cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); httpMD5String(sum, a2); /* @@ -88,12 +83,9 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ */ snprintf(line, sizeof(line), "%s:%s:%s", md5, nonce, a2); + cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); - _cupsMD5Init(&state); - _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); - _cupsMD5Finish(&state, sum); - - return (httpMD5String(sum, md5)); + return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); } @@ -106,23 +98,5 @@ httpMD5String(const unsigned char *sum, /* I - MD5 sum data */ char md5[33]) /* O - MD5 sum in hex */ { - int i; /* Looping var */ - char *md5ptr; /* Pointer into MD5 string */ - static const char hex[] = "0123456789abcdef"; - /* Hex digits */ - - - /* - * Convert the MD5 sum to hexadecimal... - */ - - for (i = 16, md5ptr = md5; i > 0; i --, sum ++) - { - *md5ptr++ = hex[*sum >> 4]; - *md5ptr++ = hex[*sum & 15]; - } - - *md5ptr = '\0'; - - return (md5); + return ((char *)cupsHashString(sum, 16, md5, 33)); } diff --git a/scheduler/auth.c b/scheduler/auth.c index 71df9dc..e7d0006 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -72,9 +72,6 @@ static int check_authref(cupsd_client_t *con, const char *right); static int compare_locations(cupsd_location_t *a, cupsd_location_t *b); static cupsd_authmask_t *copy_authmask(cupsd_authmask_t *am, void *data); -#if !HAVE_LIBPAM -static char *cups_crypt(const char *pw, const char *salt); -#endif /* !HAVE_LIBPAM */ static void free_authmask(cupsd_authmask_t *am, void *data); #if HAVE_LIBPAM static int pam_func(int, const struct pam_message **, @@ -695,14 +692,14 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * client... */ - pass = cups_crypt(password, pw->pw_passwd); + pass = crypt(password, pw->pw_passwd); if (!pass || strcmp(pw->pw_passwd, pass)) { # ifdef HAVE_SHADOW_H if (spw) { - pass = cups_crypt(password, spw->sp_pwdp); + pass = crypt(password, spw->sp_pwdp); if (pass == NULL || strcmp(spw->sp_pwdp, pass)) { @@ -1988,129 +1985,6 @@ copy_authmask(cupsd_authmask_t *mask, /* I - Existing auth mask */ } -#if !HAVE_LIBPAM -/* - * 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms, - * as needed. - */ - -static char * /* O - Encrypted password */ -cups_crypt(const char *pw, /* I - Password string */ - const char *salt) /* I - Salt (key) string */ -{ - if (!strncmp(salt, "$1$", 3)) - { - /* - * Use MD5 passwords without the benefit of PAM; this is for - * Slackware Linux, and the algorithm was taken from the - * old shadow-19990827/lib/md5crypt.c source code... :( - */ - - int i; /* Looping var */ - unsigned long n; /* Output number */ - int pwlen; /* Length of password string */ - const char *salt_end; /* End of "salt" data for MD5 */ - char *ptr; /* Pointer into result string */ - _cups_md5_state_t state; /* Primary MD5 state info */ - _cups_md5_state_t state2; /* Secondary MD5 state info */ - unsigned char digest[16]; /* MD5 digest result */ - static char result[120]; /* Final password string */ - - - /* - * Get the salt data between dollar signs, e.g. $1$saltdata$md5. - * Get a maximum of 8 characters of salt data after $1$... - */ - - for (salt_end = salt + 3; *salt_end && (salt_end - salt) < 11; salt_end ++) - if (*salt_end == '$') - break; - - /* - * Compute the MD5 sum we need... - */ - - pwlen = strlen(pw); - - _cupsMD5Init(&state); - _cupsMD5Append(&state, (unsigned char *)pw, pwlen); - _cupsMD5Append(&state, (unsigned char *)salt, salt_end - salt); - - _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) - _cupsMD5Append(&state, digest, i > 16 ? 16 : i); - - for (i = pwlen; i > 0; i >>= 1) - _cupsMD5Append(&state, (unsigned char *)((i & 1) ? "" : pw), 1); - - _cupsMD5Finish(&state, digest); - - for (i = 0; i < 1000; i ++) - { - _cupsMD5Init(&state); - - if (i & 1) - _cupsMD5Append(&state, (unsigned char *)pw, pwlen); - else - _cupsMD5Append(&state, digest, 16); - - if (i % 3) - _cupsMD5Append(&state, (unsigned char *)salt + 3, salt_end - salt - 3); - - if (i % 7) - _cupsMD5Append(&state, (unsigned char *)pw, pwlen); - - if (i & 1) - _cupsMD5Append(&state, digest, 16); - else - _cupsMD5Append(&state, (unsigned char *)pw, pwlen); - - _cupsMD5Finish(&state, digest); - } - - /* - * Copy the final sum to the result string and return... - */ - - memcpy(result, salt, (size_t)(salt_end - salt)); - ptr = result + (salt_end - salt); - *ptr++ = '$'; - - for (i = 0; i < 5; i ++, ptr += 4) - { - n = ((((unsigned)digest[i] << 8) | (unsigned)digest[i + 6]) << 8); - - if (i < 4) - n |= (unsigned)digest[i + 12]; - else - n |= (unsigned)digest[5]; - - to64(ptr, n, 4); - } - - to64(ptr, (unsigned)digest[11], 2); - ptr += 2; - *ptr = '\0'; - - return (result); - } - else - { - /* - * Use the standard crypt() function... - */ - - return (crypt(pw, salt)); - } -} -#endif /* !HAVE_LIBPAM */ - - /* * 'free_authmask()' - Free function for auth masks. */