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