1 #include <sys/types.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <bglibs/systime.h>
5 #include "v2client.h"
6 #include "sasl.h"
7 #include "sasl_internal.h"
8 
9 static const unsigned char hex2bin[256] = {
10   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 0-15 */
11   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 16-31 */
12   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 32-47 */
13    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, /* 48-63 */
14   -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 64-79 */
15   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-95 */
16   -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 96-111 */
17   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 112-127 */
18   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 128-143 */
19   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 144-159 */
20   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 160-175 */
21   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 176-191 */
22   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 192-207 */
23   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 208-223 */
24   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 224-239 */
25   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 240-255 */
26 };
27 
response1(struct sasl_state * ss,const str * response,str * challenge)28 static int response1(struct sasl_state* ss,
29 		     const str* response, str* challenge)
30 {
31   char binresp[16];
32   const str binrespstr = { binresp, 16, 0 };
33   unsigned i;
34   unsigned j;
35   if (response->len == 0) return SASL_RESP_BAD;
36   if ((i = str_findfirst(response, ' ')) == (unsigned)-1
37       || response->len - i != 33)
38     return SASL_RESP_BAD;
39   response->s[i] = 0;
40   for (j = 0; j < 32; j += 2)
41     binresp[j/2] = hex2bin[(unsigned char)response->s[i+j]] << 4
42       | hex2bin[(unsigned char)response->s[i+j+1]];
43   return sasl_authenticate_cram(ss, response->s, "CRAM-MD5",
44 				&ss->init, &binrespstr);
45   (void)challenge;
46 }
47 
sasl_cram_md5_start(struct sasl_state * ss,const str * response,str * challenge)48 int sasl_cram_md5_start(struct sasl_state* ss,
49 			const str* response, str* challenge)
50 {
51   struct timeval tv;
52   const char* hostname;
53 
54   if (response)
55     return SASL_RESP_NOTALLOWED;
56   ss->response = response1;
57   if ((hostname = cvm_client_ucspi_domain()) == 0)
58     hostname = "unknown";
59   if (gettimeofday(&tv, 0) == -1 ||
60       !str_copys(&ss->init, "<") ||
61       !str_cati(&ss->init, getpid()) ||
62       !str_catc(&ss->init, '.') ||
63       !str_catu(&ss->init, tv.tv_sec) ||
64       !str_catc(&ss->init, '.') ||
65       !str_catuw(&ss->init, tv.tv_usec, 6, '0') ||
66       !str_catc(&ss->init, '@') ||
67       !str_cats(&ss->init, hostname) ||
68       !str_catc(&ss->init, '>') ||
69       !str_copy(challenge, &ss->init))
70     return SASL_TEMP_FAIL;
71   return SASL_CHALLENGE;
72 }
73