Line data Source code
1 : /* This file is part of the cmail project (http://cmail.rocks/)
2 : * (c) 2015 Fabian "cbdev" Stumpf
3 : * License: Simplified BSD (2-Clause)
4 : * For further information, consult LICENSE.txt
5 : */
6 :
7 21 : void sasl_reset_ctx(SASL_CONTEXT* ctx, bool data_valid){
8 21 : SASL_CONTEXT empty = {
9 : .method = SASL_INVALID,
10 : .method_data = NULL,
11 : .user = NULL
12 : };
13 :
14 21 : if(data_valid){
15 8 : if(ctx->method_data){
16 : //FIXME arbitrate this by method
17 0 : free(ctx->method_data);
18 : }
19 : }
20 :
21 21 : *ctx = empty;
22 21 : }
23 :
24 27 : void sasl_reset_user(SASL_USER* user, bool data_valid){
25 27 : SASL_USER empty = {
26 : .authorized = NULL,
27 : .authenticated = NULL
28 : };
29 :
30 27 : if(data_valid){
31 17 : if(user->authorized){
32 3 : free(user->authorized);
33 : }
34 :
35 17 : if(user->authenticated){
36 5 : free(user->authenticated);
37 : }
38 : }
39 :
40 27 : *user = empty;
41 27 : }
42 :
43 10 : SASL_METHOD sasl_scan_method(char* method){
44 10 : if(!strncasecmp(method, "plain", 5)){
45 8 : return SASL_PLAIN;
46 : }
47 :
48 2 : return SASL_INVALID;
49 : }
50 :
51 3 : int sasl_challenge(LOGGER log, SASL_CONTEXT* ctx, char** response){
52 3 : switch(ctx->method){
53 : case SASL_PLAIN:
54 3 : *response = NULL;
55 3 : return SASL_CONTINUE;
56 : default:
57 0 : logprintf(log, LOG_ERROR, "No challenge handler defined for SASL method\n");
58 0 : return SASL_ERROR_PROCESSING;
59 : }
60 :
61 : return SASL_ERROR_PROCESSING;
62 : }
63 :
64 7 : int sasl_continue(LOGGER log, SASL_CONTEXT* ctx, char* data, char** response){
65 7 : int length, off_user = 0, off_pass = 0;
66 :
67 7 : if(!response){
68 0 : logprintf(log, LOG_ERROR, "NULL response pointer in sasl_continue\n");
69 0 : return SASL_ERROR_PROCESSING;
70 : }
71 :
72 7 : switch(ctx->method){
73 : case SASL_PLAIN:
74 7 : if(!data){
75 0 : return SASL_ERROR_DATA;
76 : }
77 :
78 7 : length = auth_base64decode(log, data);
79 :
80 7 : if(length < 4){ //2x NUL, 2x min 1 byte
81 2 : logprintf(log, LOG_ERROR, "Failed to decode PLAIN authentication parameter\n");
82 2 : return SASL_ERROR_DATA;
83 : }
84 :
85 : //RFC 4616 message = [authzid] UTF8NUL authcid UTF8NUL passwd
86 : //TODO test this thoroughly
87 5 : off_user = strlen(data) + 1;
88 5 : if(off_user >= length || strlen(data + off_user) < 1 || off_user + strlen(data + off_user) >= length){
89 0 : logprintf(log, LOG_ERROR, "SASL PLAIN user read out of bounds\n");
90 0 : return SASL_ERROR_DATA;
91 : }
92 :
93 5 : off_pass = off_user + strlen(data + off_user) + 1;
94 5 : if(off_pass >= length || off_pass + strlen(data + off_pass) >= length){
95 0 : logprintf(log, LOG_ERROR, "SASL PLAIN pass read out of bounds\n");
96 0 : return SASL_ERROR_DATA;
97 : }
98 :
99 : //FIXME do not print passwords
100 5 : logprintf(log, LOG_DEBUG, "SASL PLAIN user %s pass %s\n", data + off_user, data + off_pass);
101 5 : ctx->user->authenticated = common_strdup(data + off_user);
102 5 : if(!(ctx->user->authenticated)){
103 0 : logprintf(log, LOG_ERROR, "Failed to allocate memory for authenticated user\n");
104 0 : return SASL_ERROR_PROCESSING;
105 : }
106 :
107 5 : *response = data + off_pass;
108 5 : return SASL_DATA_OK;
109 : default:
110 0 : logprintf(log, LOG_ERROR, "No continuation handler defined for SASL method\n");
111 0 : return SASL_ERROR_PROCESSING;
112 : }
113 :
114 : return SASL_ERROR_PROCESSING;
115 : }
116 :
117 10 : int sasl_begin(LOGGER log, SASL_CONTEXT* ctx, SASL_USER* user, char* method, char* data, char** response){
118 : //sanity check
119 10 : if(!ctx || !user || !method || !response){
120 0 : return SASL_ERROR_PROCESSING;
121 : }
122 :
123 10 : sasl_reset_ctx(ctx, false);
124 10 : sasl_reset_user(user, false);
125 10 : ctx->user = user;
126 :
127 : //scan method
128 10 : ctx->method = sasl_scan_method(method);
129 :
130 10 : if(ctx->method == SASL_INVALID){
131 2 : return SASL_UNKNOWN_METHOD;
132 : }
133 :
134 : //if initial supplied, handle
135 8 : if(data){
136 5 : return sasl_continue(log, ctx, data, response);
137 : }
138 :
139 3 : return sasl_challenge(log, ctx, response);
140 : }
141 :
142 1 : int sasl_cancel(SASL_CONTEXT* ctx){
143 1 : sasl_reset_ctx(ctx, true);
144 1 : return 0;
145 : }
|