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