2 ** Copyright 1998 - 2008 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "courier_auth_config.h"
13 #include "courierauthsasl.h"
15 #include "courierauthdebug.h"
16 #include "libhmac/hmac.h"
19 static int nybble(int c
)
21 if (c
>= '0' && c
<= '9') return (c
-'0');
22 if (c
>= 'a' && c
<= 'f') return (c
-'a'+10);
23 if (c
>= 'A' && c
<= 'F') return (c
-'A'+10);
27 static int do_auth_verify_cram(struct hmac_hashinfo
*hash
,
28 const char *challenge
, const char *response
,
29 const char *hashsecret
)
31 unsigned char *context
;
34 if (strlen(hashsecret
) != hash
->hh_L
*4 ||
35 strlen(response
) != hash
->hh_L
*2)
38 if ((context
=malloc(hash
->hh_L
*3)) == 0) return (-1);
40 for (i
=0; i
<hash
->hh_L
*2; i
++)
42 int a
=nybble(hashsecret
[i
*2]), b
=nybble(hashsecret
[i
*2+1]);
52 hmac_hashtext(hash
, challenge
, strlen(challenge
),
53 context
, context
+hash
->hh_L
,
54 context
+hash
->hh_L
*2);
56 for (i
=0; i
<hash
->hh_L
; i
++)
58 int a
=nybble(response
[i
*2]), b
=nybble(response
[i
*2+1]);
60 if ( (unsigned char)(a
*16+b
) !=
61 context
[hash
->hh_L
*2+i
])
71 int auth_verify_cram(struct hmac_hashinfo
*hash
,
72 const char *challenge
, const char *response
,
73 const char *hashsecret
)
77 rc
= do_auth_verify_cram(hash
, challenge
, response
, hashsecret
);
78 DPRINTF(rc
? "cram validation failed" : "cram validation succeeded");
82 int auth_get_cram(const char *authtype
, char *authdata
,
83 struct cram_callback_info
*craminfo
)
89 if (strncmp(authtype
, "cram-", 5) ||
90 (craminfo
->challenge
=strtok(authdata
, "\n")) == 0 ||
91 (craminfo
->response
=strtok(0, "\n")) == 0)
93 DPRINTF("Unsupported authentication type: %s", authtype
);
98 for (i
=0; hmac_list
[i
]; i
++)
99 if (strcmp(hmac_list
[i
]->hh_name
, authtype
+5) == 0)
102 DPRINTF("cram: challenge=%s, response=%s", craminfo
->challenge
,
105 if (hmac_list
[i
] == 0
106 || (challenge_l
=authsasl_frombase64(craminfo
->challenge
)) < 0
107 || (response_l
=authsasl_frombase64(craminfo
->response
)) < 0)
109 DPRINTF("cram: invalid base64 encoding, or unknown method: %s",
114 craminfo
->h
=hmac_list
[i
];
116 for (i
=response_l
; i
> 0; )
118 if (craminfo
->response
[i
-1] == ' ')
125 DPRINTF("cram: invalid base64 encoding");
129 craminfo
->response
[i
-1]=0;
130 craminfo
->user
= craminfo
->response
;
131 craminfo
->response
+= i
;
134 /* Since base64decoded data is always lesser in size (at least),
135 ** we can do the following:
137 craminfo
->challenge
[challenge_l
]=0;
138 craminfo
->response
[response_l
]=0;
140 /* we rely on DPRINTF doing a "safe" print here */
141 DPRINTF("cram: decoded challenge/response, username '%s'",
146 int auth_cram_callback(struct authinfo
*a
, void *vp
)
148 struct cram_callback_info
*cci
=(struct cram_callback_info
*)vp
;
149 unsigned char *hashbuf
;
152 static const char hex
[]="0123456789abcdef";
159 hmac->hh_L*2 will be the size of the binary hash.
161 hmac->hh_L*4+1 will therefore be size of the binary hash,
162 as a hexadecimal string.
165 if ((hashbuf
=malloc(cci
->h
->hh_L
*6+1)) == 0)
168 hmac_hashkey(cci
->h
, a
->clearpasswd
, strlen(a
->clearpasswd
),
169 hashbuf
, hashbuf
+cci
->h
->hh_L
);
171 p
=hashbuf
+cci
->h
->hh_L
*2;
173 for (i
=0; i
<cci
->h
->hh_L
*2; i
++)
177 c
= hex
[ (hashbuf
[i
] >> 4) & 0x0F];
180 c
= hex
[ hashbuf
[i
] & 0x0F];
186 rc
=auth_verify_cram(cci
->h
, cci
->challenge
, cci
->response
,
187 (const char *)hashbuf
+cci
->h
->hh_L
*2);
192 return (*cci
->callback_func
)(a
, cci
->callback_arg
);