Merge branch 'debian'
[hcoop/debian/courier-authlib.git] / authsaslclientcram.c
CommitLineData
d9898ee8 1
2/*
ac40fd9e 3** Copyright 2000-2008 Double Precision, Inc. See COPYING for
d9898ee8 4** distribution information.
5*/
6
7#include "courier_auth_config.h"
8#include "courierauthsasl.h"
d9898ee8 9#include "libhmac/hmac.h"
d9898ee8 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
d9898ee8 17int authsaslclient_cram(const struct authsaslclientinfo *info,
ac40fd9e 18 const char *challenge,
19 const struct hmac_hashinfo *hashinfo)
d9898ee8 20{
21char *base64buf=malloc(strlen(challenge)+1);
22unsigned char *keybuf;
23char *p;
24const char *userid=info->userid ? info->userid:"";
25const char *password=info->password ? info->password:"";
26int 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}