krb5int_arcfour_string_to_key does not support utf-8 strings
authorAlexandra Ellwood <lxs@mit.edu>
Tue, 26 Feb 2008 22:18:15 +0000 (22:18 +0000)
committerAlexandra Ellwood <lxs@mit.edu>
Tue, 26 Feb 2008 22:18:15 +0000 (22:18 +0000)
krb5int_arcfour_string_to_key converts C strings to UTF-16 before passing
them to the string to key function.  Currently the UTF-16 conversion assumes
the input string is ASCII only.

Added support to convert UTF-8 strings to UTF-16 on Mac OS X.  Leaving the
bug open until we discuss if we want to have implementations for Unix and
Windows platforms.

ticket: new
status: open
target_version: 1.7

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20242 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/crypto/arcfour/arcfour_s2k.c

index 6ccfdb78322646d723d88475689d5a66fa59b134..30ef7d77ce254a9a84337a5f2fe13f7c8fa6a026 100644 (file)
@@ -2,13 +2,51 @@
 #include "rsa-md4.h"
 #include "arcfour-int.h"
 
-static void asctouni(unsigned char *unicode, unsigned char *ascii, size_t len)
+#if TARGET_OS_MAC
+#include <CoreFoundation/CFString.h>
+#endif
+
+static krb5_error_code 
+utf8to16(unsigned char *utf16_buf, const char *utf8_str, size_t *len)
 {
+    krb5_error_code err = 0;
+    
+#if TARGET_OS_MAC
+    CFStringRef string = NULL;
+    CFIndex length = *len;
+    
+    string = CFStringCreateWithCString (kCFAllocatorDefault, 
+                                        utf8_str, kCFStringEncodingUTF8);
+    if (!string) { err = ENOMEM; }
+    
+    if (!err) {
+        CFIndex copied = 0;
+        CFRange range = CFRangeMake (0, CFStringGetLength (string));
+
+        copied = CFStringGetBytes (string, range, kCFStringEncodingUTF16LE, 
+                                   0, false, utf16_buf, length, &length);
+        if (copied != range.length) { err = ENOMEM; }
+    }
+    
+    if (!err) {
+        *len = length;
+    }
+    
+    if (string) { CFRelease (string); }
+    
+#else
+    /* 
+     * This should be re-evaluated in the future, it makes the assumption that
+     * the user's password is in ascii, not utf-8.  Use iconv?
+     */     
        size_t counter;
-       for (counter=0;counter<len;counter++) {
-               unicode[2*counter]=ascii[counter];
-               unicode[2*counter + 1]=0x00;
+       for (counter=0;counter<*len;counter++) {
+               utf16_buf[2*counter]=utf8_str[counter];
+               utf16_buf[2*counter + 1]=0x00;
        }
+#endif
+    
+    return err;
 }
 
 krb5_error_code
@@ -16,6 +54,7 @@ krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
                              const krb5_data *string, const krb5_data *salt,
                              const krb5_data *params, krb5_keyblock *key)
 {
+  krb5_error_code err = 0;
   size_t len,slen;
   unsigned char *copystr;
   krb5_MD4_CTX md4_context;
@@ -31,9 +70,6 @@ krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
   /* compute the space needed for the new string.
      Since the password must be stored in unicode, we need to increase
      that number by 2x.
-
-     This should be re-evauated in the future, it makes the assumption that
-     thes user's password is in ascii.
   */
   slen = ((string->length)>128)?128:string->length;
   len=(slen)*2;
@@ -43,7 +79,8 @@ krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
     return ENOMEM;
 
   /* make the string.  start by creating the unicode version of the password*/
-  asctouni(copystr, (unsigned char *) string->data, slen);
+  err = utf8to16(copystr, string->data, &len);
+  if (err) goto cleanup;
 
   /* the actual MD4 hash of the data */
   krb5_MD4Init(&md4_context);
@@ -62,9 +99,10 @@ krb5int_arcfour_string_to_key(const struct krb5_enc_provider *enc,
   }
 #endif /* 0 */
 
+cleanup:
   /* Zero out the data behind us */
   memset (copystr, 0, len);
   memset(&md4_context, 0, sizeof(md4_context));
   free(copystr);
-  return 0;
+  return err;
 }