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