]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Add support for hashed job-password values; right now just SHA-1 and SHA-2 hashes
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 18 Nov 2015 17:22:38 +0000 (17:22 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 18 Nov 2015 17:22:38 +0000 (17:22 +0000)
(<rdar://problem/20221502>)

- Add new cupsHashData API
- Use cupsHashData in _cupsConvertOptions.
- Grab the job-password-encryption-supported value from the printer and pick the most
  secure hash that is supported.
- Add a new _CUPS_API_2_2 availability macro.
- Update dependencies and Xcode project settings.

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@12983 a1ca3aef-8c08-0410-bb20-df032aa958be

CHANGES.txt
backend/ipp.c
cgi-bin/Dependencies
cups/Dependencies
cups/Makefile
cups/cups.h
cups/hash.c [new file with mode: 0644]
cups/ppd-cache.c
cups/versioning.h
xcode/CUPS.xcodeproj/project.pbxproj

index 05722be21f151c61f9970d6aa9ee925a8edc6339..3e3edb78bf0186d9ab0da73dc1a25771b4d48764 100644 (file)
@@ -1,4 +1,4 @@
-CHANGES.txt - 2.2b1 - 2015-10-19
+CHANGES.txt - 2.2b1 - 2015-11-18
 --------------------------------
 
 CHANGES IN CUPS V2.2b1
@@ -6,4 +6,6 @@ CHANGES IN CUPS V2.2b1
        - The cupsd domain socket is no longer world-accessible on OS X
          (<rdar://problem/7542560>)
        - Interface scripts are no longer supported for security reasons
-         (<rdar://problem/23135640>)
\ No newline at end of file
+         (<rdar://problem/23135640>)
+       - Added a new cupsHashData API and support for hashed job passwords
+         (<rdar://problem/20221502>)
index 2376da4e77424eb31575951e34effba0a8f96425..5d0fc662d6496cd593625efc04f0ebf4c8430f53 100644 (file)
@@ -108,6 +108,7 @@ static const char * const pattrs[] =        /* Printer attributes we want */
   "copies-supported",
   "cups-version",
   "document-format-supported",
+  "job-password-encryption-supported",
   "marker-colors",
   "marker-high-levels",
   "marker-levels",
@@ -249,6 +250,7 @@ main(int  argc,                             /* I - Number of command-line args */
 #endif /* HAVE_LIBZ */
   ipp_attribute_t *copies_sup;         /* copies-supported */
   ipp_attribute_t *cups_version;       /* cups-version */
+  ipp_attribute_t *encryption_sup;     /* job-password-encryption-supported */
   ipp_attribute_t *format_sup;         /* document-format-supported */
   ipp_attribute_t *job_auth;           /* job-authorization-uri */
   ipp_attribute_t *media_col_sup;      /* media-col-supported */
@@ -880,6 +882,7 @@ main(int  argc,                             /* I - Number of command-line args */
 #endif /* HAVE_LIBZ */
   copies_sup           = NULL;
   cups_version         = NULL;
+  encryption_sup       = NULL;
   format_sup           = NULL;
   media_col_sup        = NULL;
   supported            = NULL;
@@ -1125,6 +1128,8 @@ main(int  argc,                           /* I - Number of command-line args */
 
     cups_version = ippFindAttribute(supported, "cups-version", IPP_TAG_TEXT);
 
+    encryption_sup = ippFindAttribute(supported, "job-password-encryption-supported", IPP_TAG_KEYWORD);
+
     if ((format_sup = ippFindAttribute(supported, "document-format-supported",
                                       IPP_TAG_MIMETYPE)) != NULL)
     {
@@ -1309,6 +1314,41 @@ main(int  argc,                          /* I - Number of command-line args */
       if ((mandatory = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
         strlcpy(mandatory_attrs, mandatory->value, sizeof(mandatory_attrs));
     }
+
+   /*
+    * Validate job-password/-encryption...
+    */
+
+    if (cupsGetOption("job-password", num_options, options))
+    {
+      const char *keyword;             /* job-password-encryption value */
+      static const char * const hashes[] =
+      {                                        /* List of supported hash algorithms, in order of preference */
+        "sha-512",
+        "sha-384",
+        "sha-512_256",
+        "sha-512-224",
+        "sha-256",
+        "sha-224",
+        "sha",
+        "none"
+      };
+
+      if ((keyword = cupsGetOption("job-password-encryption", num_options, options)) == NULL || !ippContainsString(encryption_sup, keyword))
+      {
+       /*
+        * Either no job-password-encryption or the value isn't supported by
+        * the printer...
+        */
+
+        for (i = 0; i < (int)(sizeof(hashes) / sizeof(hashes[0])); i ++)
+          if (ippContainsString(encryption_sup, hashes[i]))
+            break;
+
+        if (i < (int)(sizeof(hashes) / sizeof(hashes[0])))
+          num_options = cupsAddOption("job-password-encryption", hashes[i], num_options, &options);
+      }
+    }
   }
   else
     num_options = 0;
index 66ffa01e195a2c8b0f830c59ba845ceabe4d8bad..9dda29c78ac63ba4bbe3cbd1ddece46cef898fdb 100644 (file)
@@ -35,7 +35,8 @@ admin.o: admin.c cgi-private.h cgi.h ../cups/cups.h ../cups/file.h \
   ../cups/language.h ../cups/pwg.h help-index.h ../cups/debug-private.h \
   ../cups/language-private.h ../cups/transcode.h \
   ../cups/string-private.h ../config.h ../cups/ipp-private.h \
-  ../cups/adminutil.h ../cups/ppd.h
+  ../cups/http-private.h ../cups/md5-private.h ../cups/ppd-private.h \
+  ../cups/ppd.h ../cups/pwg-private.h ../cups/adminutil.h
 classes.o: classes.c cgi-private.h cgi.h ../cups/cups.h ../cups/file.h \
   ../cups/versioning.h ../cups/ipp.h ../cups/http.h ../cups/array.h \
   ../cups/language.h ../cups/pwg.h help-index.h ../cups/debug-private.h \
index 64a0d19d10be10cef0e22f587b18c153540bc553..e667d3920f798d8d381a8c42e6c741fcf89debd7 100644 (file)
@@ -110,6 +110,12 @@ globals.o: globals.c cups-private.h string-private.h ../config.h \
   md5-private.h language-private.h ../cups/transcode.h pwg-private.h \
   ../cups/cups.h file.h pwg.h ppd-private.h ../cups/ppd.h \
   thread-private.h
+hash.o: hash.c cups-private.h string-private.h ../config.h \
+  debug-private.h ../cups/versioning.h array-private.h ../cups/array.h \
+  ipp-private.h ../cups/ipp.h http.h http-private.h ../cups/language.h \
+  md5-private.h language-private.h ../cups/transcode.h pwg-private.h \
+  ../cups/cups.h file.h pwg.h ppd-private.h ../cups/ppd.h \
+  thread-private.h
 http.o: http.c cups-private.h string-private.h ../config.h \
   debug-private.h ../cups/versioning.h array-private.h ../cups/array.h \
   ipp-private.h ../cups/ipp.h http.h http-private.h ../cups/language.h \
@@ -269,6 +275,11 @@ testadmin.o: testadmin.c adminutil.h cups.h file.h versioning.h ipp.h \
   http.h array.h language.h pwg.h string-private.h ../config.h
 testarray.o: testarray.c string-private.h ../config.h debug-private.h \
   ../cups/versioning.h array-private.h ../cups/array.h dir.h
+testcache.o: testcache.c ppd-private.h ../cups/cups.h file.h versioning.h \
+  ipp.h http.h array.h language.h pwg.h ../cups/ppd.h pwg-private.h \
+  file-private.h cups-private.h string-private.h ../config.h \
+  debug-private.h array-private.h ipp-private.h http-private.h \
+  md5-private.h language-private.h ../cups/transcode.h thread-private.h
 testconflicts.o: testconflicts.c cups.h file.h versioning.h ipp.h http.h \
   array.h language.h pwg.h ppd.h string-private.h ../config.h
 testcups.o: testcups.c string-private.h ../config.h cups.h file.h \
@@ -316,3 +327,9 @@ testsnmp.o: testsnmp.c cups-private.h string-private.h ../config.h \
   md5-private.h language-private.h ../cups/transcode.h pwg-private.h \
   ../cups/cups.h file.h pwg.h ppd-private.h ../cups/ppd.h \
   thread-private.h snmp-private.h
+tlscheck.o: tlscheck.c cups-private.h string-private.h ../config.h \
+  debug-private.h ../cups/versioning.h array-private.h ../cups/array.h \
+  ipp-private.h ../cups/ipp.h http.h http-private.h ../cups/language.h \
+  md5-private.h language-private.h ../cups/transcode.h pwg-private.h \
+  ../cups/cups.h file.h pwg.h ppd-private.h ../cups/ppd.h \
+  thread-private.h
index 60df442a2bcf73a4ae034ffafbfecd359d2a7103..dc6859b8c55233457b8ae11910953c1fbc1f3a76 100644 (file)
@@ -51,6 +51,7 @@ LIBOBJS       =       \
                getifaddrs.o \
                getputfile.o \
                globals.o \
+               hash.o \
                http.o \
                http-addr.o \
                http-addrlist.o \
index 0fc6c9b23a34896248bfcad38ba37a90abf1582b..fbcc332a8e8144ee4942a14194c4bd83bb406d46 100644 (file)
@@ -629,6 +629,9 @@ extern const char   *cupsLocalizeDestMedia(http_t *http, cups_dest_t *dest, cups_d
 extern int             cupsMakeServerCredentials(const char *path, const char *common_name, int num_alt_names, const char **alt_names, time_t expiration_date) _CUPS_API_2_0;
 extern int             cupsSetServerCredentials(const char *path, const char *common_name, int auto_create) _CUPS_API_2_0;
 
+/* New in CUPS 2.2 */
+extern ssize_t         cupsHashData(const char *algorithm, const void *data, size_t datalen, unsigned char *hash, size_t hashsize) _CUPS_API_2_2;
+
 #  ifdef __cplusplus
 }
 #  endif /* __cplusplus */
diff --git a/cups/hash.c b/cups/hash.c
new file mode 100644 (file)
index 0000000..1d7b0db
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * "$Id$"
+ *
+ * Hashing function for CUPS.
+ *
+ * Copyright 2015 by Apple Inc.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file.  If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include "cups-private.h"
+#ifdef __APPLE__
+#  include <CommonCrypto/CommonDigest.h>
+#endif /* __APPLE__ */
+
+
+/*
+ * 'cupsHashData()' - Perform a hash function on the given data.
+ *
+ * The "algorithm" argument can be any of the registered, non-deprecated IPP
+ * hash algorithms for the "job-password-encryption" attribute, including
+ * "sha" for SHA-1, "sha-256" for SHA2-256, etc.
+ *
+ * The "hash" argument points to a buffer of "hashsize" bytes and should be at
+ * least 64 bytes in length for all of the supported algorithms.
+ *
+ * The returned hash is binary data.
+ *
+ * @since CUPS 2.2@
+ */
+
+ssize_t                                        /* O - Size of hash or -1 on error */
+cupsHashData(const char    *algorithm, /* I - Algorithm name */
+             const void    *data,      /* I - Data to hash */
+             size_t        datalen,    /* I - Length of data to hash */
+             unsigned char *hash,      /* I - Hash buffer */
+             size_t        hashsize)   /* I - Size of hash buffer */
+{
+  if (!algorithm || !data || datalen == 0 || !hash || hashsize == 0)
+  {
+    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad arguments to function"), 1);
+    return (-1);
+  }
+
+#ifdef __APPLE__
+  if (strcmp(algorithm, "sha"))
+  {
+   /*
+    * SHA-1...
+    */
+
+    CC_SHA1_CTX        ctx;                    /* SHA-1 context */
+
+    if (hashsize < CC_SHA1_DIGEST_LENGTH)
+      goto too_small;
+
+    CC_SHA1_Init(&ctx);
+    CC_SHA1_Update(&ctx, data, (CC_LONG)datalen);
+    CC_SHA1_Final(hash, &ctx);
+
+    return (CC_SHA1_DIGEST_LENGTH);
+  }
+  else if (strcmp(algorithm, "sha2-224"))
+  {
+    CC_SHA256_CTX      ctx;            /* SHA-224 context */
+
+    if (hashsize < CC_SHA224_DIGEST_LENGTH)
+      goto too_small;
+
+    CC_SHA224_Init(&ctx);
+    CC_SHA224_Update(&ctx, data, (CC_LONG)datalen);
+    CC_SHA224_Final(hash, &ctx);
+
+    return (CC_SHA224_DIGEST_LENGTH);
+  }
+  else if (strcmp(algorithm, "sha2-256"))
+  {
+    CC_SHA256_CTX      ctx;            /* SHA-256 context */
+
+    if (hashsize < CC_SHA256_DIGEST_LENGTH)
+      goto too_small;
+
+    CC_SHA256_Init(&ctx);
+    CC_SHA256_Update(&ctx, data, (CC_LONG)datalen);
+    CC_SHA256_Final(hash, &ctx);
+
+    return (CC_SHA256_DIGEST_LENGTH);
+  }
+  else if (strcmp(algorithm, "sha2-384"))
+  {
+    CC_SHA512_CTX      ctx;            /* SHA-384 context */
+
+    if (hashsize < CC_SHA384_DIGEST_LENGTH)
+      goto too_small;
+
+    CC_SHA384_Init(&ctx);
+    CC_SHA384_Update(&ctx, data, (CC_LONG)datalen);
+    CC_SHA384_Final(hash, &ctx);
+
+    return (CC_SHA384_DIGEST_LENGTH);
+  }
+  else if (strcmp(algorithm, "sha2-512"))
+  {
+    CC_SHA512_CTX      ctx;            /* SHA-512 context */
+
+    if (hashsize < CC_SHA512_DIGEST_LENGTH)
+      goto too_small;
+
+    CC_SHA512_Init(&ctx);
+    CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
+    CC_SHA512_Final(hash, &ctx);
+
+    return (CC_SHA512_DIGEST_LENGTH);
+  }
+  else if (strcmp(algorithm, "sha2-512_224"))
+  {
+    CC_SHA512_CTX      ctx;            /* SHA-512 context */
+    unsigned char      temp[CC_SHA512_DIGEST_LENGTH];
+                                        /* SHA-512 hash */
+
+   /*
+    * SHA2-512 truncated to 224 bits (28 bytes)...
+    */
+
+    if (hashsize < CC_SHA224_DIGEST_LENGTH)
+      goto too_small;
+
+    CC_SHA512_Init(&ctx);
+    CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
+    CC_SHA512_Final(temp, &ctx);
+
+    memcpy(hash, temp, CC_SHA224_DIGEST_LENGTH);
+
+    return (CC_SHA224_DIGEST_LENGTH);
+  }
+  else if (strcmp(algorithm, "sha2-512_256"))
+  {
+    CC_SHA512_CTX      ctx;            /* SHA-512 context */
+    unsigned char      temp[CC_SHA512_DIGEST_LENGTH];
+                                        /* SHA-512 hash */
+
+   /*
+    * SHA2-512 truncated to 256 bits (32 bytes)...
+    */
+
+    if (hashsize < CC_SHA256_DIGEST_LENGTH)
+      goto too_small;
+
+    CC_SHA512_Init(&ctx);
+    CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
+    CC_SHA512_Final(temp, &ctx);
+
+    memcpy(hash, temp, CC_SHA256_DIGEST_LENGTH);
+
+    return (CC_SHA256_DIGEST_LENGTH);
+  }
+
+#elif defined(HAVE_GNUTLS)
+  gnutls_digest_algorithm_t alg = GNUTLS_DIG_UNKNOWN;
+                                       /* Algorithm */
+  unsigned char        temp[64];               /* Temporary hash buffer */
+  size_t       tempsize = 0;           /* Truncate to this size? */
+
+  if (strcmp(algorithm, "sha"))
+    alg = GNUTLS_DIG_SHA1;
+  else if (strcmp(algorithm, "sha2-224"))
+    alg = GNUTLS_DIG_SHA224;
+  else if (strcmp(algorithm, "sha2-256"))
+    alg = GNUTLS_DIG_SHA256;
+  else if (strcmp(algorithm, "sha2-384"))
+    alg = GNUTLS_DIG_SHA384;
+  else if (strcmp(algorithm, "sha2-512"))
+    alg = GNUTLS_DIG_SHA512;
+  else if (strcmp(algorithm, "sha2-512_224"))
+  {
+    alg      = GNUTLS_DIG_SHA512;
+    tempsize = 28;
+  }
+  else if (strcmp(algorithm, "sha2-512_256"))
+  {
+    alg      = GNUTLS_DIG_SHA512;
+    tempsize = 32;
+  }
+
+  if (alg != GNUTLS_DIG_UNKNOWN)
+  {
+    if (tempsize > 0)
+    {
+     /*
+      * Truncate result to tempsize bytes...
+      */
+
+      if (hashsize < tempsize)
+        goto too_small;
+
+      gnutls_hash_fast(alg, data, datalen, temp);
+      memcpy(hash, temp, tempsize);
+
+      return (tempsize);
+    }
+
+    if (hashsize < gnutls_hash_get_len(alg))
+      goto too_small;
+
+    gnutls_hash_fast(alg, data, datalen, hash);
+
+    return (gnutls_hash_get_len(alg));
+  }
+
+#else
+ /*
+  * No hash support without CommonCrypto or GNU TLS...
+  */
+
+  if (hashsize < 64)
+    goto too_small;
+#endif /* __APPLE__ */
+
+ /*
+  * Unknown hash algorithm...
+  */
+
+  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown hash algorithm."), 1);
+
+  return (-1);
+
+ /*
+  * We get here if the buffer is too small.
+  */
+
+  too_small:
+
+  _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1);
+  return (-1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
index c6fe05f5dc13e050e435e127e609179926f225a0..e02129106e0fb65c50802da9f15b1d954f7bb2f6 100644 (file)
@@ -67,7 +67,8 @@ _cupsConvertOptions(ipp_t           *request, /* I - IPP request */
                    cups_option_t *options)     /* I - Options */
 {
   int          i;                      /* Looping var */
-  const char   *keyword;               /* PWG keyword */
+  const char   *keyword,               /* PWG keyword */
+               *password;              /* Password string */
   pwg_size_t   *size;                  /* PWG media size */
   ipp_t                *media_col,             /* media-col value */
                *media_size;            /* media-size value */
@@ -85,14 +86,36 @@ _cupsConvertOptions(ipp_t           *request,       /* I - IPP request */
   * Send standard IPP attributes...
   */
 
-  if (pc->password && (keyword = cupsGetOption("job-password", num_options, options)) != NULL && ippGetOperation(request) != IPP_OP_VALIDATE_JOB)
+  if (pc->password && (password = cupsGetOption("job-password", num_options, options)) != NULL && ippGetOperation(request) != IPP_OP_VALIDATE_JOB)
   {
-    ippAddOctetString(request, IPP_TAG_OPERATION, "job-password", keyword, (int)strlen(keyword));
+    ipp_attribute_t    *attr = NULL;   /* job-password attribute */
 
     if ((keyword = cupsGetOption("job-password-encryption", num_options, options)) == NULL)
       keyword = "none";
 
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "job-password-encryption", NULL, keyword);
+    if (!strcmp(keyword, "none"))
+    {
+     /*
+      * Add plain-text job-password...
+      */
+
+      attr = ippAddOctetString(request, IPP_TAG_OPERATION, "job-password", password, (int)strlen(password));
+    }
+    else
+    {
+     /*
+      * Add hashed job-password...
+      */
+
+      unsigned char    hash[64];       /* Hash of password */
+      ssize_t          hashlen;        /* Length of hash */
+
+      if ((hashlen = cupsHashData(keyword, password, strlen(password), hash, sizeof(hash))) > 0)
+        attr = ippAddOctetString(request, IPP_TAG_OPERATION, "job-password", hash, (int)hashlen);
+    }
+
+    if (attr)
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "job-password-encryption", NULL, keyword);
   }
 
   if (pc->account_id)
index 26e9a0193a867c25272da56989a2b13993d16d0a..ff52d6088b83160bd8efe79900742f8d3649a0b7 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   API versioning definitions for CUPS.
  *
- *   Copyright 2007-2013 by Apple Inc.
+ *   Copyright 2007-2015 by Apple Inc.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Apple Inc. and are protected by Federal copyright
@@ -66,6 +66,7 @@
 #    define _CUPS_API_1_6 AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER
 #    define _CUPS_API_1_7 AVAILABLE_MAC_OS_X_VERSION_10_9_AND_LATER
 #    define _CUPS_API_2_0 AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER
+#    define _CUPS_API_2_2
 #  else
 #    define _CUPS_API_1_1_19
 #    define _CUPS_API_1_1_20
@@ -77,6 +78,7 @@
 #    define _CUPS_API_1_6
 #    define _CUPS_API_1_7
 #    define _CUPS_API_2_0
+#    define _CUPS_API_2_2
 #  endif /* __APPLE__ && !_CUPS_SOURCE */
 
 /*
index 6f85ea915268045a901fe26ea58a6ca1a16db7d5..5575db3418fb555e38ccfa22e4ee89c1589f8847 100644 (file)
                7271883D1374AB14001A2036 /* mime-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7271883C1374AB14001A2036 /* mime-private.h */; };
                727AD5B719100A58009F6862 /* tls.c in Sources */ = {isa = PBXBuildFile; fileRef = 727AD5B619100A58009F6862 /* tls.c */; };
                727AD5B819100A58009F6862 /* tls.c in Sources */ = {isa = PBXBuildFile; fileRef = 727AD5B619100A58009F6862 /* tls.c */; };
+               7284F9F01BFCCDB10026F886 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 7284F9EF1BFCCD940026F886 /* hash.c */; };
+               7284F9F11BFCCDB20026F886 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 7284F9EF1BFCCD940026F886 /* hash.c */; };
                728FB7E91536161C005426E1 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 278C58E5136B64AF00836530 /* CoreFoundation.framework */; };
                728FB7EA1536161C005426E1 /* Kerberos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 278C58E6136B64B000836530 /* Kerberos.framework */; };
                728FB7EB1536161C005426E1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 278C58E7136B64B000836530 /* Security.framework */; };
                727EF04D192E3602001EF690 /* testlpd.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = testlpd.c; path = ../scheduler/testlpd.c; sourceTree = "<group>"; };
                727EF04E192E3602001EF690 /* testspeed.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = testspeed.c; path = ../scheduler/testspeed.c; sourceTree = "<group>"; };
                727EF04F192E3602001EF690 /* testsub.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = testsub.c; path = ../scheduler/testsub.c; sourceTree = "<group>"; };
+               7284F9EF1BFCCD940026F886 /* hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hash.c; path = ../cups/hash.c; sourceTree = "<group>"; };
                728FB7EC1536161C005426E1 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
                728FB7EF1536167A005426E1 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = /usr/lib/libiconv.dylib; sourceTree = "<absolute>"; };
                728FB7F01536167A005426E1 /* libresolv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libresolv.dylib; path = /usr/lib/libresolv.dylib; sourceTree = "<absolute>"; };
                                72220EDB133305BB00FCA411 /* getifaddrs.c */,
                                72220EDC133305BB00FCA411 /* getputfile.c */,
                                72220EDD133305BB00FCA411 /* globals.c */,
+                               7284F9EF1BFCCD940026F886 /* hash.c */,
                                72220EE2133305BB00FCA411 /* http.c */,
                                72220EDE133305BB00FCA411 /* http-addr.c */,
                                72220EDF133305BB00FCA411 /* http-addrlist.c */,
                72BF96371333042100B1EAD7 /* Project object */ = {
                        isa = PBXProject;
                        attributes = {
-                               LastUpgradeCheck = 0600;
+                               LastUpgradeCheck = 0710;
                                ORGANIZATIONNAME = "Apple Inc.";
                                TargetAttributes = {
                                        27A0347A1A8BDB1200650675 = {
                                274FF6A61333B1C400317ECB /* mark.c in Sources */,
                                274FF6A71333B1C400317ECB /* md5.c in Sources */,
                                274FF6A81333B1C400317ECB /* md5passwd.c in Sources */,
+                               7284F9F11BFCCDB20026F886 /* hash.c in Sources */,
                                274FF6A91333B1C400317ECB /* notify.c in Sources */,
                                274FF6AA1333B1C400317ECB /* options.c in Sources */,
                                727AD5B819100A58009F6862 /* tls.c in Sources */,
                                72220F26133305BB00FCA411 /* localize.c in Sources */,
                                72220F27133305BB00FCA411 /* mark.c in Sources */,
                                72220F29133305BB00FCA411 /* md5.c in Sources */,
+                               7284F9F01BFCCDB10026F886 /* hash.c in Sources */,
                                72220F2A133305BB00FCA411 /* md5passwd.c in Sources */,
                                72220F2B133305BB00FCA411 /* notify.c in Sources */,
                                72220F2C133305BB00FCA411 /* options.c in Sources */,