17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate #include <stdio.h>
77c478bd9Sstevel@tonic-gate #include <string.h>
87c478bd9Sstevel@tonic-gate #include "lber.h"
97c478bd9Sstevel@tonic-gate #include "ldap.h"
107c478bd9Sstevel@tonic-gate #include "ldap-int.h"
117c478bd9Sstevel@tonic-gate #include <sys/types.h>
127c478bd9Sstevel@tonic-gate #include <strings.h>
137c478bd9Sstevel@tonic-gate #include "sec.h"
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate /* text is the challenge, key is the password, digest is an allocated
167c478bd9Sstevel@tonic-gate buffer (min 16 chars) which will contain the resulting digest */
hmac_md5(unsigned char * text,int text_len,unsigned char * key,int key_len,unsigned char * digest)177c478bd9Sstevel@tonic-gate void hmac_md5(unsigned char *text, int text_len, unsigned char *key,
187c478bd9Sstevel@tonic-gate int key_len, unsigned char *digest)
197c478bd9Sstevel@tonic-gate {
207c478bd9Sstevel@tonic-gate MD5_CTX context;
217c478bd9Sstevel@tonic-gate unsigned char k_ipad[65];
227c478bd9Sstevel@tonic-gate unsigned char k_opad[65];
237c478bd9Sstevel@tonic-gate unsigned char tk[16];
247c478bd9Sstevel@tonic-gate int i;
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate if (key_len > 64){
277c478bd9Sstevel@tonic-gate MD5_CTX tctx;
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate (void) MD5Init(&tctx);
307c478bd9Sstevel@tonic-gate (void) MD5Update(&tctx, key, key_len);
317c478bd9Sstevel@tonic-gate (void) MD5Final(tk, &tctx);
327c478bd9Sstevel@tonic-gate key = tk;
337c478bd9Sstevel@tonic-gate key_len = 16;
347c478bd9Sstevel@tonic-gate }
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate bzero(k_ipad, sizeof (k_ipad));
377c478bd9Sstevel@tonic-gate bzero(k_opad, sizeof (k_opad));
387c478bd9Sstevel@tonic-gate bcopy(key, k_ipad, key_len);
397c478bd9Sstevel@tonic-gate bcopy(key, k_opad, key_len);
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate for (i=0; i<64; i++){
427c478bd9Sstevel@tonic-gate k_ipad[i] ^= 0x36;
437c478bd9Sstevel@tonic-gate k_opad[i] ^= 0x5c;
447c478bd9Sstevel@tonic-gate }
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate /* Perform inner MD5 */
477c478bd9Sstevel@tonic-gate (void) MD5Init(&context);
487c478bd9Sstevel@tonic-gate (void) MD5Update(&context, k_ipad, 64);
497c478bd9Sstevel@tonic-gate (void) MD5Update(&context, text, text_len);
507c478bd9Sstevel@tonic-gate (void) MD5Final(digest, &context);
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /* Perform outer MD5 */
537c478bd9Sstevel@tonic-gate (void) MD5Init(&context);
547c478bd9Sstevel@tonic-gate (void) MD5Update(&context, k_opad, 64);
557c478bd9Sstevel@tonic-gate (void) MD5Update(&context, digest, 16);
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate (void) MD5Final(digest, &context);
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate return;
607c478bd9Sstevel@tonic-gate }
617c478bd9Sstevel@tonic-gate
ldap_sasl_cram_md5_bind_s(LDAP * ld,char * dn,struct berval * cred,LDAPControl ** serverctrls,LDAPControl ** clientctrls)627c478bd9Sstevel@tonic-gate int ldap_sasl_cram_md5_bind_s(
637c478bd9Sstevel@tonic-gate LDAP *ld,
647c478bd9Sstevel@tonic-gate char *dn,
657c478bd9Sstevel@tonic-gate struct berval *cred,
667c478bd9Sstevel@tonic-gate LDAPControl **serverctrls,
67*1da57d55SToomas Soome LDAPControl **clientctrls )
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate int res;
707c478bd9Sstevel@tonic-gate struct berval *challenge = NULL;
717c478bd9Sstevel@tonic-gate struct berval resp;
727c478bd9Sstevel@tonic-gate unsigned char digest[16];
737c478bd9Sstevel@tonic-gate char *theHDigest;
74*1da57d55SToomas Soome
757c478bd9Sstevel@tonic-gate if (dn == NULL){
767c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR);
777c478bd9Sstevel@tonic-gate }
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate bzero(digest, sizeof (digest));
80*1da57d55SToomas Soome
817c478bd9Sstevel@tonic-gate if ((res = ldap_sasl_bind_s(ld, NULL, LDAP_SASL_CRAM_MD5, NULL, serverctrls, clientctrls, &challenge))
827c478bd9Sstevel@tonic-gate != LDAP_SASL_BIND_IN_PROGRESS){
837c478bd9Sstevel@tonic-gate return (res);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate if (challenge == NULL){
867c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR);
877c478bd9Sstevel@tonic-gate }
88*1da57d55SToomas Soome
897c478bd9Sstevel@tonic-gate LDAPDebug (LDAP_DEBUG_TRACE, "SASL challenge: %s\n", challenge->bv_val, 0, 0);
90*1da57d55SToomas Soome
91*1da57d55SToomas Soome hmac_md5((unsigned char *)challenge->bv_val, challenge->bv_len,
927c478bd9Sstevel@tonic-gate (unsigned char *)cred->bv_val, cred->bv_len, digest);
937c478bd9Sstevel@tonic-gate ber_bvfree(challenge);
947c478bd9Sstevel@tonic-gate challenge = NULL;
95*1da57d55SToomas Soome
967c478bd9Sstevel@tonic-gate theHDigest = hexa_print(digest, 16);
977c478bd9Sstevel@tonic-gate if (theHDigest == NULL){
987c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate resp.bv_len = (strlen(dn) + 32 + 1);
1027c478bd9Sstevel@tonic-gate if ((resp.bv_val = (char *)malloc(resp.bv_len+1)) == NULL) {
1037c478bd9Sstevel@tonic-gate return(LDAP_NO_MEMORY);
1047c478bd9Sstevel@tonic-gate }
105*1da57d55SToomas Soome
1067c478bd9Sstevel@tonic-gate sprintf(resp.bv_val, "%s %s", dn, theHDigest);
1077c478bd9Sstevel@tonic-gate free(theHDigest);
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate LDAPDebug (LDAP_DEBUG_TRACE, "SASL response: %s\n", resp.bv_val, 0, 0);
1107c478bd9Sstevel@tonic-gate res = ldap_sasl_bind_s(ld, NULL, LDAP_SASL_CRAM_MD5, &resp, serverctrls, clientctrls, &challenge);
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gate free(resp.bv_val);
1137c478bd9Sstevel@tonic-gate return (res);
1147c478bd9Sstevel@tonic-gate }
115