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