diff -u -r1.107 passwd.c --- passwd.c 7 Jan 2008 23:20:06 -0000 1.107 +++ passwd.c 1 Apr 2008 03:13:13 -0000 @@ -119,6 +119,9 @@ #endif #endif +static LUTIL_PASSWD_CHK_FUNC chk_piglatin; +static LUTIL_PASSWD_HASH_FUNC hash_piglatin; + /* password hash routines */ #ifdef SLAPD_CLEARTEXT @@ -154,6 +157,7 @@ { BER_BVC("{CLEARTEXT}"), NULL, hash_clear }, #endif + { BER_BVC("{X-PIGLATIN}"), chk_piglatin, hash_piglatin }, { BER_BVNULL, NULL, NULL } }; @@ -1127,3 +1131,78 @@ } #endif +static int +chk_piglatin( + const struct berval *sc, + const struct berval * passwd, + const struct berval * cred, + const char **text ) +{ + struct berval credhash; + int rc; + + rc = hash_piglatin( sc, cred, &credhash, NULL ); + if( rc != LUTIL_PASSWD_OK ) return rc; + + rc = passwd->bv_len == credhash.bv_len + && memcmp( passwd->bv_val, + credhash.bv_val, + credhash.bv_len ) == 0 ? + LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK; + + ber_memfree( credhash.bv_val ); + return rc; +} + +/* Implement {X-PIGLATIN} + * See http://en.wikipedia.org/wiki/Pig_latin + * -yay variation for leading vowels used + * y is considered a vowel unless it is the leading char + */ + +static int +hash_piglatin( + const struct berval *scheme, + const struct berval *passwd, + struct berval *hash, + const char **text ) +{ + struct berval digest; + int c, rc, first_vowel = 0; + + hash->bv_len = scheme->bv_len + passwd->bv_len + 2; + hash->bv_val = ber_memalloc( scheme->bv_len + passwd->bv_len + 4 ); + if( !hash->bv_val ) return LUTIL_PASSWD_ERR; + + for( c = 0; c < passwd->bv_len; ++c ) { + switch( passwd->bv_val[c] & -33 ) { + case 'Y': + if( c==0 ) break; + case 'A': + case 'E': + case 'I': + case 'O': + case 'U': + first_vowel = c; + goto got_vowel; + } + } + +got_vowel: + if( first_vowel ) { + char * pos = hash->bv_val; + pos += sprintf( pos, "%s%s", + scheme->bv_val, + passwd->bv_val+first_vowel ); + snprintf( pos, first_vowel+1, "%s", + passwd->bv_val ); + pos += first_vowel; + sprintf( pos, "ay" ); + } else { + sprintf( hash->bv_val, "%s%syay", + scheme->bv_val, passwd->bv_val ); + hash->bv_len += 1; + } + + return LUTIL_PASSWD_OK; +}