1 
2 /*
3 ** Copyright 2000-2008 Double Precision, Inc.  See COPYING for
4 ** distribution information.
5 */
6 
7 #include	"courier_auth_config.h"
8 #include	"courierauthsasl.h"
9 #include	"libhmac/hmac.h"
10 #include	"authsaslclient.h"
11 #include	<stdlib.h>
12 #include	<stdio.h>
13 #include	<ctype.h>
14 #include	<string.h>
15 #include	<errno.h>
16 
authsaslclient_cram(const struct authsaslclientinfo * info,const char * challenge,const struct hmac_hashinfo * hashinfo)17 int authsaslclient_cram(const struct authsaslclientinfo *info,
18 			const char *challenge,
19 			const struct hmac_hashinfo *hashinfo)
20 {
21 char	*base64buf=malloc(strlen(challenge)+1);
22 unsigned char	*keybuf;
23 char *p;
24 const	char *userid=info->userid ? info->userid:"";
25 const	char *password=info->password ? info->password:"";
26 int	i;
27 
28 	if (!base64buf)
29 	{
30 		perror("malloc");
31 		return (AUTHSASL_ERROR);
32 	}
33 	strcpy(base64buf, challenge);
34 
35 	if ( (i=authsasl_frombase64(base64buf))<0 ||
36 	     (keybuf=(unsigned char *)malloc(hashinfo->hh_L*3)) == 0)
37 	{
38 		free(base64buf);
39 		perror("malloc");
40 		return (AUTHSASL_ERROR);
41 	}
42 
43 	hmac_hashkey( hashinfo, password, strlen(password),
44                         keybuf, keybuf+hashinfo->hh_L );
45 
46 	hmac_hashtext( hashinfo, base64buf, i,
47                 keybuf, keybuf+hashinfo->hh_L,
48                 keybuf+hashinfo->hh_L*2);
49 
50 	free(base64buf);
51 	base64buf=malloc(strlen(userid)+2+hashinfo->hh_L*2);
52 	if (!base64buf)
53 	{
54 		perror("malloc");
55 		free(keybuf);
56 		return (AUTHSASL_ERROR);
57 	}
58 	strcat(strcpy(base64buf, userid), " ");
59 	p=base64buf+strlen(base64buf);
60 	for (i=0; i<hashinfo->hh_L; i++)
61 	{
62 	static const char xdigit[]="0123456789abcdef";
63 	int	c=keybuf[hashinfo->hh_L*2+i];
64 
65 		*p++ = xdigit[ (c >> 4) & 0x0F ];
66 		*p++ = xdigit[c & 0x0F];
67         }
68 	*p=0;
69 	free(keybuf);
70 	keybuf=(unsigned char *)authsasl_tobase64(base64buf, -1);
71 	free(base64buf);
72 
73 	if (!keybuf)
74 	{
75 		perror("malloc");
76 		free(keybuf);
77 		return (AUTHSASL_ERROR);
78 	}
79 	i= (*info->final_conv_func)((char *)keybuf, info->conv_func_arg);
80 	free(keybuf);
81 	return (i);
82 }
83