"Fossies" - the Fresh Open Source Software Archive 
Member "libspf2-1.2.10/src/libspf2/spf_id2str.c" (28 Jan 2012, 9935 Bytes) of package /linux/privat/libspf2-1.2.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "spf_id2str.c" see the
Fossies "Dox" file reference documentation.
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of either:
4 *
5 * a) The GNU Lesser General Public License as published by the Free
6 * Software Foundation; either version 2.1, or (at your option) any
7 * later version,
8 *
9 * OR
10 *
11 * b) The two-clause BSD license.
12 *
13 * These licenses can be found with the distribution in the file LICENSES
14 */
15
16 #include "spf_sys_config.h"
17
18
19
20 #ifdef STDC_HEADERS
21 # include <stdio.h> /* stdin / stdout */
22 # include <stdlib.h> /* malloc / free */
23 # include <ctype.h> /* isupper / tolower */
24 #endif
25
26 #ifdef HAVE_INTTYPES_H
27 #include <inttypes.h>
28 #endif
29
30 #ifdef HAVE_STRING_H
31 # include <string.h> /* strstr / strdup */
32 #else
33 # ifdef HAVE_STRINGS_H
34 # include <strings.h> /* strstr / strdup */
35 # endif
36 #endif
37
38
39 #include "spf.h"
40 #include "spf_internal.h"
41
42
43 static SPF_errcode_t
44 SPF_record_stringify_data(SPF_data_t *data, SPF_data_t *data_end,
45 char **p_p, char *p_end,
46 int is_mod, int cidr_ok, int debug )
47 {
48 char *p = *p_p;
49
50 size_t len;
51
52 SPF_data_t *cidr_data;
53
54 if (debug)
55 SPF_debugf(" string data: Building");
56
57 if (p_end - p <= 0)
58 return SPF_E_INTERNAL_ERROR;
59
60 cidr_data = NULL;
61 if ( data < data_end && data->dc.parm_type == PARM_CIDR )
62 {
63 if (debug)
64 SPF_debugf(" string data: Found a CIDR at %p", data);
65 if ( !cidr_ok )
66 return SPF_E_INTERNAL_ERROR;
67
68 cidr_data = data;
69 data = SPF_data_next( data );
70 }
71
72
73 for( ; data < data_end; data = SPF_data_next( data ) )
74 {
75 if (debug)
76 SPF_debugf(" string data: Handling data type %d at %p",
77 data->ds.parm_type, data);
78 if ( data->ds.parm_type == PARM_STRING )
79 {
80 char *s = SPF_data_str( data );
81 char *s_end = s + data->ds.len;
82 if (debug)
83 SPF_debugf(" string data: String is [%d] '%*.*s'",
84 data->ds.len, data->ds.len, data->ds.len, s);
85
86 if (p_end - (p + data->ds.len) <= 0)
87 return SPF_E_INTERNAL_ERROR;
88
89 while (s < s_end) {
90 if (*s == ' ') {
91 *p++ = '%';
92 *p++ = '_';
93 s++;
94 }
95 else if (*s == '%') {
96 *p++ = '%';
97 s++;
98 if (s[0] == '2' && s[1] == '0') {
99 *p++ = '-';
100 s += 2;
101 }
102 else {
103 *p++ = '%';
104 // *p++ = '%';
105 }
106 }
107 else {
108 *p++ = *s++;
109 }
110 }
111
112 if (p_end - p <= 0)
113 return SPF_E_INTERNAL_ERROR;
114 }
115 else if (data->dc.parm_type == PARM_CIDR) {
116 /* Two CIDRs in a row is invalid. */
117 return SPF_E_INVALID_CIDR;
118 }
119 else {
120 len = snprintf( p, p_end - p, "%%{" );
121 p += len;
122 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
123
124
125 if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
126 switch( data->dv.parm_type )
127 {
128 case PARM_LP_FROM: /* local-part of envelope-sender */
129 *p = 'l';
130 break;
131
132 case PARM_ENV_FROM: /* envelope-sender */
133 *p = 's';
134 break;
135
136 case PARM_DP_FROM: /* envelope-domain */
137 *p = 'o';
138 break;
139
140 case PARM_CUR_DOM: /* current-domain */
141 *p = 'd';
142 break;
143
144 case PARM_CLIENT_IP: /* SMTP client IP */
145 *p = 'i';
146 break;
147
148 case PARM_CLIENT_IP_P: /* SMTP client IP (pretty) */
149 *p = 'c';
150 break;
151
152 case PARM_TIME: /* time in UTC epoch secs */
153 if ( !is_mod )
154 return SPF_E_INVALID_VAR;
155 *p = 't';
156 break;
157
158 case PARM_CLIENT_DOM: /* SMTP client domain name */
159 *p = 'p';
160 break;
161
162 case PARM_CLIENT_VER: /* IP ver str - in-addr/ip6 */
163 *p = 'v';
164 break;
165
166 case PARM_HELO_DOM: /* HELO/EHLO domain */
167 *p = 'h';
168 break;
169
170 case PARM_REC_DOM: /* receiving domain */
171 *p = 'r';
172 break;
173
174 default:
175 return SPF_E_INVALID_VAR;
176 break;
177 }
178 if ( data->dv.url_encode )
179 *p = toupper( *p );
180 p++;
181 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
182
183
184 if ( data->dv.num_rhs )
185 {
186 len = snprintf( p, p_end - p, "%d", data->dv.num_rhs );
187 p += len;
188 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
189 }
190
191
192 if ( p_end - p <= 8 ) return SPF_E_INTERNAL_ERROR;
193 if ( data->dv.rev )
194 *p++ = 'r';
195
196 if ( data->dv.delim_dot
197 && ( data->dv.delim_dash
198 || data->dv.delim_plus
199 || data->dv.delim_equal
200 || data->dv.delim_bar
201 || data->dv.delim_under
202 )
203 )
204 *p++ = '.';
205 if ( data->dv.delim_dash )
206 *p++ = '-';
207 if ( data->dv.delim_plus )
208 *p++ = '+';
209 if ( data->dv.delim_equal )
210 *p++ = '=';
211 if ( data->dv.delim_bar )
212 *p++ = '|';
213 if ( data->dv.delim_under )
214 *p++ = '_';
215
216 *p++ = '}';
217 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
218 }
219 }
220
221
222 if ( cidr_data )
223 {
224 if ( cidr_data->dc.ipv4 )
225 {
226 len = snprintf( p, p_end - p, "/%d", cidr_data->dc.ipv4 );
227 p += len;
228 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
229 }
230
231 if ( cidr_data->dc.ipv6 )
232 {
233 len = snprintf( p, p_end - p, "//%d", cidr_data->dc.ipv6 );
234 p += len;
235 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
236 }
237 }
238
239 *p_p = p;
240 return SPF_E_SUCCESS;
241 }
242
243
244 SPF_errcode_t
245 SPF_record_stringify( SPF_record_t *spf_record, char **bufp, size_t *buflenp)
246 {
247 int i;
248 SPF_mech_t *mech;
249 SPF_mod_t *mod;
250
251 SPF_data_t *data, *data_end;
252
253 size_t len;
254 const char *p_err;
255 char *p, *p_end;
256
257 char ip4_buf[ INET_ADDRSTRLEN ];
258 char ip6_buf[ INET6_ADDRSTRLEN ];
259
260 int cidr_ok;
261 SPF_errcode_t err;
262
263 #define debug spf_record->spf_server->debug
264
265 SPF_ASSERT_NOTNULL(spf_record);
266
267 /*
268 * make sure the return buffer is big enough
269 *
270 * The worse case for the version string:
271 * "v=spf1 " = 6 = 4
272 * The worst cases for mechanisms
273 * "ip4:111.222.333.444/31 " = 23 < 6 * 3.9
274 * "ip6:<full-ipv6-spec>/126 " = 49 < 18 * 2.8
275 * "-include:x " = 11 = 5 * 2.2
276 * "-all " = 5 = 2 * 2.5
277 *
278 * The worst case for modifiers:
279 * "a=%{i15r.-+=|_} " = 16 = 5 * 3.2
280 */
281
282 len = sizeof( SPF_VER_STR )
283 + spf_record->mech_len * 4 + spf_record->mod_len * 4 /* data */
284 + sizeof( "\0" );
285
286 err = SPF_recalloc(bufp, buflenp, len);
287 if (err != SPF_E_SUCCESS)
288 return err;
289
290 p = *bufp;
291 p_end = *bufp + *buflenp;
292
293 if (debug)
294 SPF_debugf("stringify: Buffer length is %lu\n", (unsigned long)*buflenp);
295
296
297 /*
298 * generate SPF version string
299 */
300 len = snprintf(p, p_end - p, "v=spf%d", spf_record->version);
301 p += len;
302 if (p_end - p <= 0)
303 return SPF_E_INTERNAL_ERROR;
304
305
306 /*
307 * generate mechanisms
308 */
309
310 mech = spf_record->mech_first;
311 for (i = 0; i < spf_record->num_mech; i++) {
312 if (debug)
313 SPF_debugf("stringify: Handling mechanism %d/%d at %p",
314 i, spf_record->num_mech, mech);
315 if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
316 *p++ = ' ';
317
318
319 if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
320 switch( mech->prefix_type )
321 {
322 case PREFIX_PASS:
323 /* *p++ = '+'; */
324 break;
325
326 case PREFIX_FAIL:
327 *p++ = '-';
328 break;
329
330 case PREFIX_SOFTFAIL:
331 *p++ = '~';
332 break;
333
334 case PREFIX_NEUTRAL:
335 *p++ = '?';
336 break;
337
338 case PREFIX_UNKNOWN:
339 return SPF_E_RESULT_UNKNOWN;
340 break;
341
342 default:
343 return SPF_E_INVALID_PREFIX;
344 break;
345 }
346
347 if (debug)
348 SPF_debugf("Mechanism type is %d", mech->mech_type);
349
350 switch( mech->mech_type )
351 {
352 case MECH_A:
353 len = snprintf( p, p_end - p, "a" );
354 break;
355
356 case MECH_MX:
357 len = snprintf( p, p_end - p, "mx" );
358 break;
359
360 case MECH_PTR:
361 len = snprintf( p, p_end - p, "ptr" );
362 break;
363
364 case MECH_INCLUDE:
365 len = snprintf( p, p_end - p, "include" );
366 break;
367
368 case MECH_IP4:
369 p_err = inet_ntop( AF_INET, SPF_mech_ip4_data( mech ),
370 ip4_buf, sizeof( ip4_buf ) );
371 if ( p_err == NULL )
372 return SPF_E_INTERNAL_ERROR;
373 if ( mech->mech_len )
374 len = snprintf( p, p_end - p, "ip4:%s/%d",
375 ip4_buf, mech->mech_len );
376 else
377 len = snprintf( p, p_end - p, "ip4:%s", ip4_buf );
378 break;
379
380 case MECH_IP6:
381 p_err = inet_ntop( AF_INET6, SPF_mech_ip6_data( mech ),
382 ip6_buf, sizeof( ip6_buf ) );
383 if ( p_err == NULL )
384 return SPF_E_INTERNAL_ERROR;
385 if ( mech->mech_len )
386 len = snprintf( p, p_end - p, "ip6:%s/%d",
387 ip6_buf, mech->mech_len );
388 else
389 len = snprintf( p, p_end - p, "ip6:%s", ip6_buf );
390 break;
391
392 case MECH_EXISTS:
393 len = snprintf( p, p_end - p, "exists" );
394 break;
395
396 case MECH_ALL:
397 len = snprintf( p, p_end - p, "all" );
398 break;
399
400 case MECH_REDIRECT:
401 len = snprintf( p, p_end - p, "redirect" );
402 break;
403
404 default:
405 return SPF_E_UNKNOWN_MECH;
406 break;
407 }
408 p += len;
409 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
410
411 if (debug)
412 SPF_debugf("stringify: Buffer so far is %s", p);
413
414 if ( mech->mech_type != MECH_IP4 && mech->mech_type != MECH_IP6 )
415 {
416 data = SPF_mech_data( mech );
417 data_end = SPF_mech_end_data( mech );
418
419 if (SPF_mech_data_len(mech) > 0
420 /* We have an immediate string literal */
421 && (data->dc.parm_type != PARM_CIDR
422 /* Some data follows the CIDR */
423 || SPF_data_next( data ) < data_end)
424 ) {
425 *p++ = ':';
426 }
427
428 cidr_ok = mech->mech_type == MECH_A || mech->mech_type == MECH_MX;
429 err = SPF_record_stringify_data(
430 data, data_end,
431 &p, p_end,
432 FALSE, cidr_ok, debug );
433
434 if ( err != SPF_E_SUCCESS )
435 return err;
436 }
437
438 mech = SPF_mech_next( mech );
439 }
440
441
442 /*
443 * generate modifiers
444 */
445
446 mod = spf_record->mod_first;
447 for( i = 0; i < spf_record->num_mod; i++ )
448 {
449 if (debug)
450 SPF_debugf("stringify: Handling modifier %d/%d at %p",
451 i, spf_record->num_mod, mod);
452 if ( p_end - p <= 1 ) return SPF_E_INTERNAL_ERROR;
453 *p++ = ' ';
454
455 len = snprintf( p, p_end - p, "%.*s=",
456 mod->name_len, SPF_mod_name( mod ) );
457 p += len;
458 if ( p_end - p <= 0 ) return SPF_E_INTERNAL_ERROR;
459
460 data = SPF_mod_data( mod );
461 data_end = SPF_mod_end_data( mod );
462
463 err = SPF_record_stringify_data(
464 data, data_end,
465 &p, p_end,
466 TRUE, TRUE, debug );
467
468 if ( err != SPF_E_SUCCESS )
469 return err;
470
471
472 mod = SPF_mod_next( mod );
473 }
474
475
476
477 *p++ = '\0';
478
479 return SPF_E_SUCCESS;
480 }