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 static int do_auth_get_cram(const char *authtype
, char *authdata
,
83 struct cram_callback_info
*craminfo
, int logerr
)
89 if (strncmp(authtype
, "cram-", 5) ||
90 (craminfo
->challenge
=strtok(authdata
, "\n")) == 0 ||
91 (craminfo
->response
=strtok(0, "\n")) == 0)
95 DPRINTF("Unsupported authentication type: %s", authtype
);
101 for (i
=0; hmac_list
[i
]; i
++)
102 if (strcmp(hmac_list
[i
]->hh_name
, authtype
+5) == 0)
107 DPRINTF("cram: challenge=%s, response=%s", craminfo
->challenge
,
111 if (hmac_list
[i
] == 0
112 || (challenge_l
=authsasl_frombase64(craminfo
->challenge
)) < 0
113 || (response_l
=authsasl_frombase64(craminfo
->response
)) < 0)
117 DPRINTF("cram: invalid base64 encoding, or unknown method: %s",
123 craminfo
->h
=hmac_list
[i
];
125 for (i
=response_l
; i
> 0; )
127 if (craminfo
->response
[i
-1] == ' ')
136 DPRINTF("cram: invalid base64 encoding");
141 craminfo
->response
[i
-1]=0;
142 craminfo
->user
= craminfo
->response
;
143 craminfo
->response
+= i
;
146 /* Since base64decoded data is always lesser in size (at least),
147 ** we can do the following:
149 craminfo
->challenge
[challenge_l
]=0;
150 craminfo
->response
[response_l
]=0;
154 /* we rely on DPRINTF doing a "safe" print here */
155 DPRINTF("cram: decoded challenge/response, username '%s'",
161 int auth_cram_callback(struct authinfo
*a
, void *vp
)
163 struct cram_callback_info
*cci
=(struct cram_callback_info
*)vp
;
164 unsigned char *hashbuf
;
167 static const char hex
[]="0123456789abcdef";
174 hmac->hh_L*2 will be the size of the binary hash.
176 hmac->hh_L*4+1 will therefore be size of the binary hash,
177 as a hexadecimal string.
180 if ((hashbuf
=malloc(cci
->h
->hh_L
*6+1)) == 0)
183 hmac_hashkey(cci
->h
, a
->clearpasswd
, strlen(a
->clearpasswd
),
184 hashbuf
, hashbuf
+cci
->h
->hh_L
);
186 p
=hashbuf
+cci
->h
->hh_L
*2;
188 for (i
=0; i
<cci
->h
->hh_L
*2; i
++)
192 c
= hex
[ (hashbuf
[i
] >> 4) & 0x0F];
195 c
= hex
[ hashbuf
[i
] & 0x0F];
201 rc
=auth_verify_cram(cci
->h
, cci
->challenge
, cci
->response
,
202 (const char *)hashbuf
+cci
->h
->hh_L
*2);
207 return (*cci
->callback_func
)(a
, cci
->callback_arg
);
210 int auth_get_cram(const char *authtype
, char *authdata
,
211 struct cram_callback_info
*craminfo
)
213 return do_auth_get_cram(authtype
, authdata
, craminfo
, 1);
216 int auth_get_cram_silent(const char *authtype
, char *authdata
,
217 struct cram_callback_info
*craminfo
)
219 return do_auth_get_cram(authtype
, authdata
, craminfo
, 0);