1 #include <string.h>
2 #include <bglibs/base64.h>
3 #include <bglibs/iobuf.h>
4 #include <bglibs/msg.h>
5 #include <bglibs/str.h>
6 #include "sasl.h"
7 #include "v2client.h"
8
sasl_auth_init(struct sasl_auth * sa)9 int sasl_auth_init(struct sasl_auth* sa)
10 {
11 if (sa->prefix == 0)
12 sa->prefix = "";
13 if (sa->suffix == 0)
14 sa->suffix = "\r\n";
15 if (sa->in == 0)
16 sa->in = &inbuf;
17 if (sa->out == 0)
18 sa->out = &outbuf;
19 return sasl_init(&sa->state);
20 }
21
sasl_auth_caps(str * caps)22 int sasl_auth_caps(str* caps)
23 {
24 const struct sasl_mechanism* smech;
25 if (!sasl_mechanisms)
26 return 0;
27
28 if (!str_truncate(caps, 0) ||
29 !str_copys(caps, "AUTH"))
30 return -1;
31 for (smech = sasl_mechanisms; smech != 0; smech = smech->next)
32 if (!str_catc(caps, ' ') || !str_cats(caps, smech->name))
33 return -1;
34 return 1;
35 }
36
sasl_auth2(struct sasl_auth * sa,const char * mechanism,const char * init_response)37 int sasl_auth2(struct sasl_auth* sa,
38 const char* mechanism,
39 const char* init_response)
40 {
41 str challenge = {0,0,0};
42 str challenge64 = {0,0,0};
43 str response = {0,0,0};
44 str response64 = {0,0,0};
45 int i;
46 str* iresponsestr;
47
48 if (init_response != 0) {
49 if (!str_truncate(&response, 0))
50 return -1;
51 if (!base64_decode_line(init_response, &response)) {
52 msg3("SASL AUTH ", mechanism, " failed: bad response");
53 str_free(&response);
54 return SASL_RESP_BAD;
55 }
56 iresponsestr = &response;
57 }
58 else
59 iresponsestr = 0;
60 i = sasl_start(&sa->state, mechanism, iresponsestr, &challenge);
61 while (i == SASL_CHALLENGE) {
62 i = -1;
63 if (str_truncate(&challenge64, 0)
64 && base64_encode_line((const unsigned char*)challenge.s,
65 challenge.len, &challenge64)
66 && obuf_puts(sa->out, sa->prefix)
67 && obuf_putstr(sa->out, &challenge64)
68 && obuf_putsflush(sa->out, sa->suffix)
69 && ibuf_getstr_crlf(sa->in, &response64)) {
70 if (response64.len == 0 || response64.s[0] == '*') {
71 msg3("SASL AUTH ", mechanism, " failed: aborted");
72 i = SASL_AUTH_FAILED;
73 }
74 else if (!str_truncate(&response, 0) ||
75 !base64_decode_line(response64.s, &response)) {
76 msg3("SASL AUTH ", mechanism, " failed: bad response");
77 i = SASL_RESP_BAD;
78 }
79 else
80 i = sa->state.response(&sa->state, &response, &challenge);
81 }
82 else if (ibuf_eof(sa->in))
83 i = SASL_RESP_EOF;
84 }
85 if (i == SASL_AUTH_OK) {
86 str_truncate(&response, 0);
87 str_copys(&response, "username=");
88 str_cats(&response, cvm_fact_username);
89 if (cvm_fact_sys_username != 0) {
90 str_cats(&response, " sys_username=");
91 str_cats(&response, cvm_fact_sys_username);
92 }
93 if (cvm_fact_domain != 0 && cvm_fact_domain[0] != 0) {
94 str_cats(&response, " domain=");
95 str_cats(&response, cvm_fact_domain);
96 }
97 msg4("SASL AUTH ", mechanism, " ", response.s);
98 cvm_client_setenv();
99 }
100 else
101 msg3("SASL AUTH ", mechanism, " failed");
102 str_free(&response);
103 str_free(&response64);
104 str_free(&challenge);
105 str_free(&challenge64);
106 return i;
107 }
108
sasl_auth1(struct sasl_auth * sa,const str * arg)109 int sasl_auth1(struct sasl_auth* sa, const str* arg)
110 {
111 str mechanism = {0,0,0};
112 int s;
113 if ((s = str_findfirst(arg, ' ')) != -1) {
114 if (!str_copyb(&mechanism, arg->s, s))
115 return -1;
116 while (arg->s[s] == ' ')
117 ++s;
118 s = sasl_auth2(sa, mechanism.s, arg->s+s);
119 str_free(&mechanism);
120 }
121 else
122 s = sasl_auth2(sa, arg->s, 0);
123 return s;
124 }
125
sasl_auth_msg(int * code)126 const char* sasl_auth_msg(int* code)
127 {
128 int newcode;
129 const char* msg;
130 #define R(C,M) newcode=C; msg=M; break
131 switch (*code) {
132 case SASL_AUTH_FAILED: R(501,"Authentication failed.");
133 case SASL_NO_MECH: R(504,"Unrecognized authentication mechanism.");
134 case SASL_RESP_REQUIRED: R(535,"Response was required but not given.");
135 case SASL_RESP_NOTALLOWED: R(535,"Initial response not allowed.");
136 case SASL_RESP_BAD: R(501,"Could not decode the response.");
137 case SASL_RESP_EOF: R(535,"End of file reached.");
138 default: R(451,"Internal error.");
139 }
140 *code = newcode;
141 return msg;
142 }
143