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 29 : void sasl_reset_ctx(SASL_CONTEXT* ctx, bool data_valid){
8 29 : SASL_CONTEXT empty = {
9 : .method = SASL_INVALID,
10 : .method_data = NULL,
11 : .user = NULL
12 : };
13 :
14 29 : if(data_valid){
15 24 : if(ctx->method_data){
16 : //FIXME arbitrate this by method
17 0 : free(ctx->method_data);
18 : }
19 : }
20 :
21 29 : *ctx = empty;
22 29 : }
23 :
24 26 : void sasl_reset_user(SASL_USER* user, bool data_valid){
25 26 : SASL_USER empty = {
26 : .authorized = NULL,
27 : .authenticated = NULL
28 : };
29 :
30 26 : if(data_valid){
31 21 : if(user->authorized){
32 7 : free(user->authorized);
33 : }
34 :
35 21 : if(user->authenticated){
36 12 : free(user->authenticated);
37 : }
38 : }
39 :
40 26 : *user = empty;
41 26 : }
42 :
43 5 : SASL_METHOD sasl_scan_method(char* method){
44 5 : if(!strncasecmp(method, "plain", 5)){
45 5 : return SASL_PLAIN;
46 : }
47 :
48 0 : return SASL_INVALID;
49 : }
50 :
51 2 : int sasl_challenge(LOGGER log, SASL_CONTEXT* ctx, char** response){
52 2 : switch(ctx->method){
53 : case SASL_PLAIN:
54 2 : *response = NULL;
55 2 : 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 4 : int sasl_continue(LOGGER log, SASL_CONTEXT* ctx, char* data, char** response){
65 4 : int length, off_user = 0, off_pass = 0;
66 :
67 4 : if(!response){
68 0 : logprintf(log, LOG_ERROR, "NULL response pointer in sasl_continue\n");
69 0 : return SASL_ERROR_PROCESSING;
70 : }
71 :
72 4 : switch(ctx->method){
73 : case SASL_PLAIN:
74 4 : if(!data){
75 0 : return SASL_ERROR_DATA;
76 : }
77 :
78 4 : length = auth_base64decode(log, data);
79 :
80 4 : 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 2 : off_user = strlen(data) + 1;
88 2 : 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 2 : off_pass = off_user + strlen(data + off_user) + 1;
94 2 : 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 2 : logprintf(log, LOG_DEBUG, "SASL PLAIN user %s pass %s\n", data + off_user, data + off_pass);
101 2 : ctx->user->authenticated = common_strdup(data + off_user);
102 2 : 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 2 : *response = data + off_pass;
108 2 : 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 5 : int sasl_begin(LOGGER log, SASL_CONTEXT* ctx, SASL_USER* user, char* method, char* data, char** response){
118 : //sanity check
119 5 : if(!ctx || !user || !method || !response){
120 0 : return SASL_ERROR_PROCESSING;
121 : }
122 :
123 5 : sasl_reset_ctx(ctx, false);
124 5 : sasl_reset_user(user, false);
125 5 : ctx->user = user;
126 :
127 : //scan method
128 5 : ctx->method = sasl_scan_method(method);
129 :
130 5 : if(ctx->method == SASL_INVALID){
131 0 : return SASL_UNKNOWN_METHOD;
132 : }
133 :
134 : //if initial supplied, handle
135 5 : if(data){
136 3 : return sasl_continue(log, ctx, data, response);
137 : }
138 :
139 2 : 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 : }
|