2 ** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
3 ** distribution information.
7 #include "courier_auth_config.h"
13 #include "courierauthsasl.h"
15 #include "courierauthdebug.h"
19 #include "libhmac/hmac.h"
22 static int nybble(int c
)
24 if (c
>= '0' && c
<= '9') return (c
-'0');
25 if (c
>= 'a' && c
<= 'f') return (c
-'a'+10);
26 if (c
>= 'A' && c
<= 'F') return (c
-'A'+10);
30 static int do_auth_verify_cram(struct hmac_hashinfo
*hash
,
31 const char *challenge
, const char *response
,
32 const char *hashsecret
)
34 unsigned char *context
;
37 if (strlen(hashsecret
) != hash
->hh_L
*4 ||
38 strlen(response
) != hash
->hh_L
*2)
41 if ((context
=malloc(hash
->hh_L
*3)) == 0) return (-1);
43 for (i
=0; i
<hash
->hh_L
*2; i
++)
45 int a
=nybble(hashsecret
[i
*2]), b
=nybble(hashsecret
[i
*2+1]);
55 hmac_hashtext(hash
, challenge
, strlen(challenge
),
56 context
, context
+hash
->hh_L
,
57 context
+hash
->hh_L
*2);
59 for (i
=0; i
<hash
->hh_L
; i
++)
61 int a
=nybble(response
[i
*2]), b
=nybble(response
[i
*2+1]);
63 if ( (unsigned char)(a
*16+b
) !=
64 context
[hash
->hh_L
*2+i
])
74 int auth_verify_cram(struct hmac_hashinfo
*hash
,
75 const char *challenge
, const char *response
,
76 const char *hashsecret
)
80 rc
= do_auth_verify_cram(hash
, challenge
, response
, hashsecret
);
81 DPRINTF(rc
? "cram validation failed" : "cram validation succeeded");
85 int auth_get_cram(const char *authtype
, char *authdata
,
86 struct cram_callback_info
*craminfo
)
92 if (strncmp(authtype
, "cram-", 5) ||
93 (craminfo
->challenge
=strtok(authdata
, "\n")) == 0 ||
94 (craminfo
->response
=strtok(0, "\n")) == 0)
96 DPRINTF("cram: only supports authtype=cram-*");
101 for (i
=0; hmac_list
[i
]; i
++)
102 if (strcmp(hmac_list
[i
]->hh_name
, authtype
+5) == 0)
105 DPRINTF("cram: challenge=%s, response=%s", craminfo
->challenge
,
108 if (hmac_list
[i
] == 0
109 || (challenge_l
=authsasl_frombase64(craminfo
->challenge
)) < 0
110 || (response_l
=authsasl_frombase64(craminfo
->response
)) < 0)
112 DPRINTF("cram: invalid base64 encoding, or unknown method: %s",
117 craminfo
->h
=hmac_list
[i
];
119 for (i
=response_l
; i
> 0; )
121 if (craminfo
->response
[i
-1] == ' ')
128 DPRINTF("cram: invalid base64 encoding");
132 craminfo
->response
[i
-1]=0;
133 craminfo
->user
= craminfo
->response
;
134 craminfo
->response
+= i
;
137 /* Since base64decoded data is always lesser in size (at least),
138 ** we can do the following:
140 craminfo
->challenge
[challenge_l
]=0;
141 craminfo
->response
[response_l
]=0;
143 /* we rely on DPRINTF doing a "safe" print here */
144 DPRINTF("cram: decoded challenge/response, username '%s'",
149 int auth_cram_callback(struct authinfo
*a
, void *vp
)
151 struct cram_callback_info
*cci
=(struct cram_callback_info
*)vp
;
152 unsigned char *hashbuf
;
155 static const char hex
[]="0123456789abcdef";
162 hmac->hh_L*2 will be the size of the binary hash.
164 hmac->hh_L*4+1 will therefore be size of the binary hash,
165 as a hexadecimal string.
168 if ((hashbuf
=malloc(cci
->h
->hh_L
*6+1)) == 0)
171 hmac_hashkey(cci
->h
, a
->clearpasswd
, strlen(a
->clearpasswd
),
172 hashbuf
, hashbuf
+cci
->h
->hh_L
);
174 p
=hashbuf
+cci
->h
->hh_L
*2;
176 for (i
=0; i
<cci
->h
->hh_L
*2; i
++)
180 c
= hex
[ (hashbuf
[i
] >> 4) & 0x0F];
183 c
= hex
[ hashbuf
[i
] & 0x0F];
189 rc
=auth_verify_cram(cci
->h
, cci
->challenge
, cci
->response
,
190 (const char *)hashbuf
+cci
->h
->hh_L
*2);
195 return (*cci
->callback_func
)(a
, cci
->callback_arg
);