non-ascii password in kerberos authentication

Xu Qiang Qiang.Xu at fujixerox.com
Mon Sep 17 04:26:21 EDT 2007


> -----Original Message-----
> From: Ken Raeburn [mailto:raeburn at MIT.EDU]
> Sent: Monday, September 17, 2007 12:12 PM
> To: Xu Qiang
> Cc: Paul Moore; krbdev at mit.edu
> Subject: Re: non-ascii password in kerberos authentication
> 
> I can think of some workarounds, none especially pretty.
> 
> * If you can be sure that RC4 is being used, convert to UCS-2LE
> before calling into the library in the first place.
> 
> * Modify the MIT code you're using to be aware that you're always
> passing in UTF-8, and in the RC4 string-to-key code, always convert
> to UCS-2LE.  Because of the transition issues and possible existing
> deployments using other approaches, I'm not sure if we would be able
> to incorporate a patch for this, but we can discuss it.  I think it
> would get the job done for you, though.

A function is written to convert:
=========================================================
static char * character_converter(char *fromCode, char *toCode, const char *infield)
{	
	/*
	** The UTF-8 character conversion can take up to 2 bytes of space, which is double
	** the size of normal ascii character allocation for ldap attributes which is defined
	** in MAX_ATTRIBUTE_LENGTH.  This doubled plus 1 for the null terminator.
	*/
  	char outbuf[MAX_ATTRIBUTE_LENGTH*2+1];
  	static char convertedBuf[MAX_ATTRIBUTE_LENGTH*2+1];
  	char* outptr = outbuf;
    	size_t outsize = sizeof(outbuf);
  	size_t result = 0;
  	const char *inptr = infield;
  	size_t insize = strlen(infield); 
	int saved_errno = 0;
	iconv_t cd;
	
	cd = iconv_open(toCode, fromCode);
	if (cd == (iconv_t)(-1)) {
		fprintf(stderr, "Failed to perform iconv_open\n");
		return (NULL);
	}
	
  	iconv(cd, NULL, NULL, NULL, NULL);

    /*
    ** call the iconv library to perform the conversion.
    */
    fprintf(stderr, "ENTER THE ICONV FUNCTION CALL!\n");
    result = iconv(cd, (const char**)&inptr, &insize, &outptr, &outsize);
    fprintf(stderr, "EXIT THE ICONV FUNCTION CALL!\n");
   	/*
   	** check for error conditions.
   	*/
   	
   	if (result == (size_t)(-1)) {
   		fprintf(stderr, "\nIN THE CHARACTER CONVERTER\n");
        	if (errno == EILSEQ) {
            		fprintf(stderr, "iconv: %s: cannot convert\n", inptr);
            		iconv_close(cd);
            		return (NULL);
          	} 
    		else if (errno == EINVAL) {
            		if (insize > (MAX_ATTRIBUTE_LENGTH*2+1)) {
              			fprintf(stderr, "iconv: %s: incomplete character or shift sequence\n", inptr);
              			iconv_close(cd);
              			return (NULL);
            		}
          	}
		else if (errno != E2BIG) {
            		saved_errno = errno;
            		fprintf(stderr, "iconv: [%s]: \n", inptr);
            		errno = saved_errno;
            		perror("");
            		iconv_close(cd);
            		return (NULL);
          	}
        }
    
    
    /*
    ** Check to make certain that the returned size is correct. Not exactly sure what this comparison is
    ** doing for us.  outptr vs outbuf was taken directly from the iconv source code as is.  required
    ** for this to work.
    */
    
    if (outptr != outbuf) {
    	int saved_errno = errno;
    
    	/*
    	** save off the result into the convertedBuf.
    	*/
        memset(convertedBuf, '\0', (MAX_ATTRIBUTE_LENGTH*2+1));
        strncpy(convertedBuf, outbuf, outptr-outbuf);
        errno = saved_errno;
    }
  
  /*
  ** close descriptor.
  */
  iconv_close(cd);
  
  return (convertedBuf);
}
=========================================================
Originally, the function was written to convert ISO-8859-1 to UTF-8, but i think it should be OK to use it to convert to UCS-2LE. Essentially the function calls system library function "iconv()" to do the job.

I am calling it with:
=========================================================
#define	UCS_2LE			"UCS-2LE"
#define	UTF_8				"UTF-8"
#define ISO_8859			"ISO-8859-1"
#define AUTH_PASSWORD_SIZE              (256)
#define MAX_ATTRIBUTE_LENGTH            (AUTH_PASSWORD_SIZE * 2)
char tmpPassword[AUTH_PASSWORD_SIZE];
char *tmpUcs2Password = NULL; 
char *password;
......
				fprintf(stderr, "before convert, password is [%s]\n", tmpPassword);
				if ((tmpUcs2Password = character_converter(ISO_8859, UCS_2LE, tmpPassword)) != NULL)
				{
					password = tmpUcs2Password;
				}
				else
				{
					fprintf(stderr, "Fail to convert character!\n");
				}
				fprintf(stderr, "after convert, password is [%s]\n", password);
=========================================================
Look quite straightforward. 

But although my passed in password is [eeFair123], the converted password is cut into only one char - [e]. It seems UCS-2LE is not supported by the system library function "iconv()"?

Need help here in conversion,
Xu Qiang




More information about the krbdev mailing list