1 /* 2 * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 #include <stdio.h> 9 #include <string.h> 10 #include "lber.h" 11 #include "ldap.h" 12 #include "ldap-int.h" 13 #include <sys/types.h> 14 #include <strings.h> 15 #include "sec.h" 16 17 /* text is the challenge, key is the password, digest is an allocated 18 buffer (min 16 chars) which will contain the resulting digest */ 19 void hmac_md5(unsigned char *text, int text_len, unsigned char *key, 20 int key_len, unsigned char *digest) 21 { 22 MD5_CTX context; 23 unsigned char k_ipad[65]; 24 unsigned char k_opad[65]; 25 unsigned char tk[16]; 26 int i; 27 28 if (key_len > 64){ 29 MD5_CTX tctx; 30 31 (void) MD5Init(&tctx); 32 (void) MD5Update(&tctx, key, key_len); 33 (void) MD5Final(tk, &tctx); 34 key = tk; 35 key_len = 16; 36 } 37 38 bzero(k_ipad, sizeof (k_ipad)); 39 bzero(k_opad, sizeof (k_opad)); 40 bcopy(key, k_ipad, key_len); 41 bcopy(key, k_opad, key_len); 42 43 for (i=0; i<64; i++){ 44 k_ipad[i] ^= 0x36; 45 k_opad[i] ^= 0x5c; 46 } 47 48 /* Perform inner MD5 */ 49 (void) MD5Init(&context); 50 (void) MD5Update(&context, k_ipad, 64); 51 (void) MD5Update(&context, text, text_len); 52 (void) MD5Final(digest, &context); 53 54 /* Perform outer MD5 */ 55 (void) MD5Init(&context); 56 (void) MD5Update(&context, k_opad, 64); 57 (void) MD5Update(&context, digest, 16); 58 59 (void) MD5Final(digest, &context); 60 61 return; 62 } 63 64 int ldap_sasl_cram_md5_bind_s( 65 LDAP *ld, 66 char *dn, 67 struct berval *cred, 68 LDAPControl **serverctrls, 69 LDAPControl **clientctrls ) 70 { 71 int res; 72 struct berval *challenge = NULL; 73 struct berval resp; 74 unsigned char digest[16]; 75 char *theHDigest; 76 77 if (dn == NULL){ 78 return (LDAP_PARAM_ERROR); 79 } 80 81 bzero(digest, sizeof (digest)); 82 83 if ((res = ldap_sasl_bind_s(ld, NULL, LDAP_SASL_CRAM_MD5, NULL, serverctrls, clientctrls, &challenge)) 84 != LDAP_SASL_BIND_IN_PROGRESS){ 85 return (res); 86 } 87 if (challenge == NULL){ 88 return (LDAP_PARAM_ERROR); 89 } 90 91 LDAPDebug (LDAP_DEBUG_TRACE, "SASL challenge: %s\n", challenge->bv_val, 0, 0); 92 93 hmac_md5((unsigned char *)challenge->bv_val, challenge->bv_len, 94 (unsigned char *)cred->bv_val, cred->bv_len, digest); 95 ber_bvfree(challenge); 96 challenge = NULL; 97 98 theHDigest = hexa_print(digest, 16); 99 if (theHDigest == NULL){ 100 return (LDAP_NO_MEMORY); 101 } 102 103 resp.bv_len = (strlen(dn) + 32 + 1); 104 if ((resp.bv_val = (char *)malloc(resp.bv_len+1)) == NULL) { 105 return(LDAP_NO_MEMORY); 106 } 107 108 sprintf(resp.bv_val, "%s %s", dn, theHDigest); 109 free(theHDigest); 110 111 LDAPDebug (LDAP_DEBUG_TRACE, "SASL response: %s\n", resp.bv_val, 0, 0); 112 res = ldap_sasl_bind_s(ld, NULL, LDAP_SASL_CRAM_MD5, &resp, serverctrls, clientctrls, &challenge); 113 114 free(resp.bv_val); 115 return (res); 116 } 117