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