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