Branch data Line data Source code
1 : : /**
2 : : * \file lib/fko_encode.c
3 : : *
4 : : * \brief Encodes some pieces of the spa data then puts together all of
5 : : * the necessary pieces to gether to create the single encoded
6 : : * message string.
7 : : */
8 : :
9 : : /* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
10 : : * Copyright (C) 2009-2015 fwknop developers and contributors. For a full
11 : : * list of contributors, see the file 'CREDITS'.
12 : : *
13 : : * License (GNU General Public License):
14 : : *
15 : : * This program is free software; you can redistribute it and/or
16 : : * modify it under the terms of the GNU General Public License
17 : : * as published by the Free Software Foundation; either version 2
18 : : * of the License, or (at your option) any later version.
19 : : *
20 : : * This program is distributed in the hope that it will be useful,
21 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 : : * GNU General Public License for more details.
24 : : *
25 : : * You should have received a copy of the GNU General Public License
26 : : * along with this program; if not, write to the Free Software
27 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 : : * USA
29 : : *
30 : : *****************************************************************************
31 : : */
32 : : #include "fko_common.h"
33 : : #include "fko.h"
34 : : #include "base64.h"
35 : : #include "digest.h"
36 : :
37 : : /* Take a given string, base64-encode it and append it to the given
38 : : * buffer.
39 : : */
40 : : static int
41 : 5417 : append_b64(char* tbuf, char *str)
42 : : {
43 : 5417 : int len = strnlen(str, MAX_SPA_ENCODED_MSG_SIZE);
44 : : char *bs;
45 : :
46 : : #if HAVE_LIBFIU
47 [ + + ]: 5417 : fiu_return_on("append_b64_toobig",
48 : : FKO_ERROR_INVALID_DATA_ENCODE_MESSAGE_TOOBIG);
49 : : #endif
50 : :
51 [ + - ]: 5416 : if(len >= MAX_SPA_ENCODED_MSG_SIZE)
52 : : return(FKO_ERROR_INVALID_DATA_ENCODE_MESSAGE_TOOBIG);
53 : :
54 : : #if HAVE_LIBFIU
55 [ + + ]: 5416 : fiu_return_on("append_b64_calloc", FKO_ERROR_MEMORY_ALLOCATION);
56 : : #endif
57 : :
58 : 5415 : bs = calloc(1, ((len/3)*4)+8);
59 [ + + ]: 5415 : if(bs == NULL)
60 : : return(FKO_ERROR_MEMORY_ALLOCATION);
61 : :
62 : 5406 : b64_encode((unsigned char*)str, bs, len);
63 : :
64 : : /* --DSS XXX: make sure to check here if later decoding
65 : : * becomes a problem.
66 : : */
67 : 5406 : strip_b64_eq(bs);
68 : :
69 : 5406 : strlcat(tbuf, bs, FKO_ENCODE_TMP_BUF_SIZE);
70 : :
71 : 5406 : free(bs);
72 : :
73 : 5406 : return(FKO_SUCCESS);
74 : : }
75 : :
76 : : /* Set the SPA encryption type.
77 : : */
78 : : int
79 : 57277 : fko_encode_spa_data(fko_ctx_t ctx)
80 : : {
81 : 57277 : int res, offset = 0;
82 : : char *tbuf;
83 : :
84 : : #if HAVE_LIBFIU
85 [ + + ]: 57277 : fiu_return_on("fko_encode_spa_data_init", FKO_ERROR_CTX_NOT_INITIALIZED);
86 : : #endif
87 : : /* Must be initialized
88 : : */
89 [ + - ][ + - ]: 57276 : if(!CTX_INITIALIZED(ctx))
90 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
91 : :
92 : : /* Check prerequisites.
93 : : * --DSS XXX: Needs review. Also, we could make this more robust (or
94 : : * (at leaset expand the error reporting for the missing
95 : : * data).
96 : : */
97 : : #if HAVE_LIBFIU
98 [ + + ]: 57276 : fiu_return_on("fko_encode_spa_data_valid", FKO_ERROR_INCOMPLETE_SPA_DATA);
99 : : #endif
100 [ + - ]: 57275 : if( validate_username(ctx->username) != FKO_SUCCESS
101 [ + - ][ + - ]: 57275 : || ctx->version == NULL || strnlen(ctx->version, MAX_SPA_VERSION_SIZE) == 0
102 [ + + ][ + - ]: 57275 : || ctx->message == NULL || strnlen(ctx->message, MAX_SPA_MESSAGE_SIZE) == 0)
103 : : {
104 : : return(FKO_ERROR_INCOMPLETE_SPA_DATA);
105 : : }
106 : :
107 [ + + ]: 2582 : if(ctx->message_type == FKO_NAT_ACCESS_MSG)
108 : : {
109 [ + - ][ + - ]: 40 : if(ctx->nat_access == NULL || strnlen(ctx->nat_access, MAX_SPA_MESSAGE_SIZE) == 0)
110 : : return(FKO_ERROR_INCOMPLETE_SPA_DATA);
111 : : }
112 : :
113 : : #if HAVE_LIBFIU
114 [ + + ]: 2582 : fiu_return_on("fko_encode_spa_data_calloc", FKO_ERROR_MEMORY_ALLOCATION);
115 : : #endif
116 : : /* Allocate our initial tmp buffer.
117 : : */
118 : 2581 : tbuf = calloc(1, FKO_ENCODE_TMP_BUF_SIZE);
119 [ + + ]: 2581 : if(tbuf == NULL)
120 : : return(FKO_ERROR_MEMORY_ALLOCATION);
121 : :
122 : : /* Put it together a piece at a time, starting with the rand val.
123 : : */
124 : 2575 : strlcpy(tbuf, ctx->rand_val, FKO_ENCODE_TMP_BUF_SIZE);
125 : :
126 : : /* Add the base64-encoded username.
127 : : */
128 : 2575 : strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
129 [ + + ]: 2575 : if((res = append_b64(tbuf, ctx->username)) != FKO_SUCCESS)
130 : : {
131 : 7 : free(tbuf);
132 : 7 : return(res);
133 : : }
134 : :
135 : : /* Add the timestamp.
136 : : */
137 : 2568 : offset = strlen(tbuf);
138 : 2568 : snprintf(((char*)tbuf+offset), FKO_ENCODE_TMP_BUF_SIZE - offset,
139 : 2568 : ":%u:", (unsigned int) ctx->timestamp);
140 : :
141 : : /* Add the version string.
142 : : */
143 : 2568 : strlcat(tbuf, ctx->version, FKO_ENCODE_TMP_BUF_SIZE);
144 : :
145 : : /* Before we add the message type value, we will once again
146 : : * check for whether or not a client_timeout was specified
147 : : * since the message_type was set. If this is the case, then
148 : : * we want to adjust the message_type first. The easy way
149 : : * to do this is simply call fko_set_spa_client_timeout and set
150 : : * it to its current value. This will force a re-check and
151 : : * possible reset of the message type.
152 : : *
153 : : */
154 : 2568 : fko_set_spa_client_timeout(ctx, ctx->client_timeout);
155 : :
156 : : /* Add the message type value.
157 : : */
158 : 2568 : offset = strlen(tbuf);
159 : 2568 : snprintf(((char*)tbuf+offset), FKO_ENCODE_TMP_BUF_SIZE - offset,
160 : 2568 : ":%i:", ctx->message_type);
161 : :
162 : : /* Add the base64-encoded SPA message.
163 : : */
164 [ + + ]: 2568 : if((res = append_b64(tbuf, ctx->message)) != FKO_SUCCESS)
165 : : {
166 : 4 : free(tbuf);
167 : 4 : return(res);
168 : : }
169 : :
170 : : /* If a nat_access message was given, add it to the SPA
171 : : * message.
172 : : */
173 [ + + ]: 2564 : if(ctx->nat_access != NULL)
174 : : {
175 : 159 : strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
176 [ - + ]: 159 : if((res = append_b64(tbuf, ctx->nat_access)) != FKO_SUCCESS)
177 : : {
178 : 0 : free(tbuf);
179 : 0 : return(res);
180 : : }
181 : : }
182 : :
183 : : /* If we have a server_auth field set. Add it here.
184 : : *
185 : : */
186 [ + + ]: 2564 : if(ctx->server_auth != NULL)
187 : : {
188 : 115 : strlcat(tbuf, ":", FKO_ENCODE_TMP_BUF_SIZE);
189 [ - + ]: 115 : if((res = append_b64(tbuf, ctx->server_auth)) != FKO_SUCCESS)
190 : : {
191 : 0 : free(tbuf);
192 : 0 : return(res);
193 : : }
194 : : }
195 : :
196 : : /* If a client timeout is specified and we are not dealing with a
197 : : * SPA command message, add the timeout here.
198 : : */
199 [ + + ][ + - ]: 2564 : if(ctx->client_timeout > 0 && ctx->message_type != FKO_COMMAND_MSG)
200 : : {
201 : 126 : offset = strlen(tbuf);
202 : 126 : snprintf(((char*)tbuf+offset), FKO_ENCODE_TMP_BUF_SIZE - offset,
203 : : ":%i", ctx->client_timeout);
204 : : }
205 : :
206 : : /* If encoded_msg is not null, then we assume it needs to
207 : : * be freed before re-assignment.
208 : : */
209 [ + + ]: 2564 : if(ctx->encoded_msg != NULL)
210 : 410 : free(ctx->encoded_msg);
211 : :
212 : : /* Copy our encoded data into the context.
213 : : */
214 : 2564 : ctx->encoded_msg = strdup(tbuf);
215 : 2564 : free(tbuf);
216 : :
217 [ + - ]: 2564 : if(ctx->encoded_msg == NULL)
218 : : return(FKO_ERROR_MEMORY_ALLOCATION);
219 : :
220 : 2564 : ctx->encoded_msg_len = strnlen(ctx->encoded_msg, MAX_SPA_ENCODED_MSG_SIZE);
221 : :
222 [ + - ]: 2564 : if(! is_valid_encoded_msg_len(ctx->encoded_msg_len))
223 : : return(FKO_ERROR_INVALID_DATA_ENCODE_MSGLEN_VALIDFAIL);
224 : :
225 : : /* At this point we can compute the digest for this SPA data.
226 : : */
227 [ + + ]: 2564 : if((res = fko_set_spa_digest(ctx)) != FKO_SUCCESS)
228 : : return(res);
229 : :
230 : : /* Here we can clear the modified flags on the SPA data fields.
231 : : */
232 : 2557 : FKO_CLEAR_SPA_DATA_MODIFIED(ctx);
233 : :
234 : 2557 : return(FKO_SUCCESS);
235 : : }
236 : :
237 : : /* Return the fko SPA encrypted data.
238 : : */
239 : : int
240 : 3929 : fko_get_encoded_data(fko_ctx_t ctx, char **enc_msg)
241 : : {
242 : : /* Must be initialized
243 : : */
244 [ + + ][ + - ]: 3929 : if(!CTX_INITIALIZED(ctx))
245 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
246 : :
247 [ + + ]: 3777 : if(enc_msg == NULL)
248 : : return(FKO_ERROR_INVALID_DATA);
249 : :
250 : 3709 : *enc_msg = ctx->encoded_msg;
251 : :
252 : 3709 : return(FKO_SUCCESS);
253 : : }
254 : :
255 : : /* Set the fko SPA encoded data (this is a convenience
256 : : * function mostly used for tests that involve fuzzing).
257 : : */
258 : : #if FUZZING_INTERFACES
259 : : int
260 : 846510 : fko_set_encoded_data(fko_ctx_t ctx,
261 : : const char * const encoded_msg, const int msg_len,
262 : : const int require_digest, const int digest_type)
263 : : {
264 : 846510 : char *tbuf = NULL;
265 : 846510 : int res = FKO_SUCCESS, mlen;
266 : :
267 : : /* Must be initialized
268 : : */
269 [ + - ][ + - ]: 846510 : if(!CTX_INITIALIZED(ctx))
270 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
271 : :
272 [ + - ]: 846510 : if(encoded_msg == NULL)
273 : : return(FKO_ERROR_INVALID_DATA);
274 : :
275 : 846510 : ctx->encoded_msg = strdup(encoded_msg);
276 : :
277 : 846510 : ctx->state |= FKO_DATA_MODIFIED;
278 : :
279 [ + - ]: 846510 : if(ctx->encoded_msg == NULL)
280 : : return(FKO_ERROR_MEMORY_ALLOCATION);
281 : :
282 : : /* allow arbitrary length (i.e. let the decode routines validate
283 : : * SPA message length).
284 : : */
285 : 846510 : ctx->encoded_msg_len = msg_len;
286 : :
287 [ + - ]: 846510 : if(require_digest)
288 : : {
289 : 846510 : fko_set_spa_digest_type(ctx, digest_type);
290 [ + + ]: 846510 : if((res = fko_set_spa_digest(ctx)) != FKO_SUCCESS)
291 : : {
292 : : return res;
293 : : }
294 : :
295 : : /* append the digest to the encoded message buffer
296 : : */
297 : 801502 : mlen = ctx->encoded_msg_len + ctx->digest_len + 2;
298 : 801502 : tbuf = calloc(1, mlen);
299 [ + - ]: 801502 : if(tbuf == NULL)
300 : : return(FKO_ERROR_MEMORY_ALLOCATION);
301 : :
302 : : /* memcpy since the provided encoded buffer might
303 : : * have an embedded NULL?
304 : : */
305 : 1603004 : mlen = snprintf(tbuf, mlen, "%s:%s", ctx->encoded_msg, ctx->digest);
306 : :
307 [ + - ]: 801502 : if(ctx->encoded_msg != NULL)
308 : 801502 : free(ctx->encoded_msg);
309 : :
310 : 801502 : ctx->encoded_msg = strdup(tbuf);
311 : 801502 : free(tbuf);
312 : :
313 [ + - ]: 801502 : if(ctx->encoded_msg == NULL)
314 : : return(FKO_ERROR_MEMORY_ALLOCATION);
315 : :
316 : 801502 : ctx->encoded_msg_len = mlen;
317 : : }
318 : :
319 : 801502 : FKO_CLEAR_SPA_DATA_MODIFIED(ctx);
320 : :
321 : 801502 : return(FKO_SUCCESS);
322 : : }
323 : : #endif
324 : :
325 : : /***EOF***/
|