"Fossies" - the Fresh Open Source Software Archive 
Member "libspf2-1.2.10/src/spf_example/spf_example.c" (28 Jan 2012, 8972 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_example.c" see the
Fossies "Dox" file reference documentation.
1 /*
2 * spf_example - An example program for how to use libspf2
3 *
4 * Author: Wayne Schlitt <wayne@midwestcs.com>
5 *
6 * File: spfquery.c
7 * Desc: SPF command line utility
8 *
9 *
10 * This program is in the public domain, there is no copyright, you
11 * can do anything you want with it.
12 */
13
14
15 /*
16 * The libspf2 library uses the GNU autoconf system to help make
17 * the library more portable. The config.h file should have the
18 * HAVE_xxx defines that are appropriate for your system. Either use
19 * autconf to create it, or create it by hand.
20 */
21
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #ifdef STDC_HEADERS
28 # include <stdio.h>
29 # include <stdlib.h> /* malloc / free */
30 #endif
31
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h> /* types (u_char .. etc..) */
34 #endif
35
36 #ifdef HAVE_INTTYPES_H
37 #include <inttypes.h>
38 #endif
39
40 #ifdef HAVE_STRING_H
41 # include <string.h> /* strstr / strdup */
42 #else
43 # ifdef HAVE_STRINGS_H
44 # include <strings.h> /* strstr / strdup */
45 # endif
46 #endif
47
48 #ifdef HAVE_SYS_SOCKET_H
49 # include <sys/socket.h> /* inet_ functions / structs */
50 #endif
51 #ifdef HAVE_NETINET_IN_H
52 # include <netinet/in.h> /* inet_ functions / structs */
53 #endif
54 #ifdef HAVE_ARPA_INET_H
55 # include <arpa/inet.h> /* in_addr struct */
56 #endif
57
58 #ifdef HAVE_ARPA_NAMESER_H
59 # include <arpa/nameser.h> /* DNS HEADER struct */
60 #endif
61
62 #ifdef HAVE_UNISTD_H
63 #include <unistd.h>
64 #endif
65
66 #ifdef HAVE_GETOPT_H
67 #include <getopt.h>
68 #endif
69
70
71
72 /*
73 * libspf2 public include files that are needed for this example
74 * program
75 */
76
77 #include "spf.h"
78
79
80 /*
81 * usage() just prints out the command line options for this program
82 */
83 static void usage()
84 {
85 fprintf(
86 stderr,
87 "Usage:\n"
88 "\n"
89 "spf_example [options]\n"
90 "\n"
91 "Valid data options are:\n"
92 " -i <IP address> The IP address that is sending email\n"
93 " -s <email address> The email address used as the\n"
94 " envelope-from. If no username (local\n"
95 " part) is given, 'postmaster' will be\n"
96 " assumed.\n"
97 " -r <email address> [optional] The email address used as\n"
98 " the envelope-to email address, for\n"
99 " secondary-MX checking.\n"
100 " -h <domain name> The domain name given on the SMTP HELO\n"
101 " command. This is only needed if the\n"
102 " -sender option is not given.\n"
103 " -d [debug level] debug level.\n"
104 );
105 }
106
107
108
109 /*
110 * All the code is in the main routine, but most usages of libspf2
111 * would have the code spread around into various subrotines.
112 */
113
114 int main( int argc, char *argv[] )
115 {
116 int c;
117 int res = 0;
118 int i;
119
120 char *opt_ip = NULL;
121 char *opt_sender = NULL;
122 char *opt_helo = NULL;
123 char *opt_rcpt_to = NULL;
124 int opt_debug = 0;
125
126 /* You should not indirect on any of these structures, as their
127 * layout may change between versions of the library. Use the
128 * accessor functions instead. Definitions of the structs may not
129 * even be provided. */
130
131 SPF_server_t *spf_server = NULL;
132 SPF_request_t *spf_request = NULL;
133 SPF_response_t *spf_response = NULL;
134 SPF_response_t *spf_response_2mx = NULL;
135
136
137 /*
138 * check the arguments
139 */
140
141 while (1)
142 {
143 c = getopt(argc, argv, "i:s:h:r:d::" );
144
145 if (c == -1)
146 break;
147
148 switch (c)
149 {
150 case 'i':
151 opt_ip = optarg;
152 break;
153
154 case 's':
155 opt_sender = optarg;
156 break;
157
158 case 'h':
159 opt_helo = optarg;
160 break;
161
162 case 'r':
163 opt_rcpt_to = optarg;
164 break;
165
166 case 0:
167 case '?':
168 usage();
169 res = 255;
170 goto error;
171 break;
172
173 case 'd':
174 if (optarg == NULL)
175 opt_debug = 1;
176 else
177 opt_debug = atoi( optarg );
178 break;
179
180 default:
181 fprintf( stderr, "Error: getopt returned character code 0%o ??\n", c);
182 }
183 }
184
185 if (optind != argc
186 || opt_ip == NULL
187 || (opt_helo == NULL && opt_sender == NULL))
188 {
189 usage();
190 res = 255;
191 goto error;
192 }
193
194 /*
195 * Configure the SPF system.
196 *
197 * libspf2 is designed so that configurations can be set up once
198 * and reused many times different emails delivered in a single SMTP
199 * session or in different SMTP sessions.
200 */
201
202 /*
203 * set up the SPF server
204 *
205 * Configurations contain malloc'd data so must be
206 * destroyed when you are finished.
207 */
208
209 spf_server = SPF_server_new(SPF_DNS_CACHE, 1);
210
211 if (spf_server == NULL) {
212 fprintf( stderr, "SPF_create_config failed.\n" );
213 res = 255;
214 goto error;
215 }
216
217 /*
218 * Create a new request.
219 *
220 * The SPF request contains all the data needed to process
221 * the SPF check. Requests are malloc'd so it must be
222 * destroyed when you are finished with it.
223 */
224
225 spf_request = SPF_request_new(spf_server);
226
227 /* The domain name of the receiving MTA will default to gethostname() */
228 /* SPF_request_set_rec_dom( spf_request, opt_name ); */
229
230
231 /*
232 * process the SPF request
233 *
234 * Now that the SPF system has been configured, we can process the requests.
235 * There would normally be a loop around this code or it would be placed
236 * in a subroutine to be called for each email.
237 *
238 * If a single email session sends several emails, you don't need to
239 * reset the IP address or the HELO domain each time, just change the
240 * envelope from.
241 */
242
243 /*
244 * record the IP address of the client (sending) MTA.
245 *
246 * There are other SPF_set_ip*() functionx if you have a structure
247 * instead of a string.
248 */
249
250 if ( SPF_request_set_ipv4_str( spf_request, opt_ip ) ) {
251 printf( "Invalid IP address.\n" );
252 res = 255;
253 goto error;
254 }
255
256
257 /*
258 * record the HELO domain name of the client (sending) MTA from
259 * the SMTP HELO or EHLO commands
260 *
261 * This domain name will be used if the envelope from address is
262 * null (e.g. MAIL FROM:<>). This happens when a bounce is being
263 * sent and, in effect, it is the client MTA that is sending the
264 * message.
265 */
266
267 if ( SPF_request_set_helo_dom( spf_request, opt_helo ) ) {
268 printf( "Invalid HELO domain.\n" );
269 res = 255;
270 goto error;
271 }
272
273 /*
274 * record the envelope from email address from the SMTP MAIL FROM:
275 * command.
276 */
277
278 if ( SPF_request_set_env_from( spf_request, opt_sender ) ) {
279 printf( "Invalid envelope from address.\n" );
280 res = 255;
281 goto error;
282 }
283
284 /*
285 * now that we have all the information, see what the result of
286 * the SPF check is.
287 */
288
289 SPF_request_query_mailfrom(spf_request, &spf_response);
290
291 /*
292 * If the sender MAIL FROM check failed, then for each SMTP RCPT TO
293 * command, the mail might have come from a secondary MX for that
294 * domain.
295 *
296 * Note that most MTAs will also check the RCPT TO command to make sure
297 * that it is ok to accept. This SPF check won't give a free pass
298 * to all secondary MXes from all domains, just the one specified by
299 * the rcpt_to address. It is assumed that the MTA checks (at some
300 * point) that we are also a valid primary or secondary for the domain.
301 */
302 if (SPF_response_result(spf_response) != SPF_RESULT_PASS) {
303 SPF_request_query_rcptto(spf_request, &spf_response_2mx, opt_rcpt_to);
304 /*
305 * We might now have a PASS if the mail came from a client which
306 * is a secondary MX from the domain specified in opt_rcpt_to.
307 *
308 * If not, then the RCPT TO: address must have been a domain for
309 * which the client is not a secondary MX, AND the MAIL FROM: domain
310 * doesn't doesn't return 'pass' from SPF_result()
311 */
312 if (SPF_response_result(spf_response_2mx) == SPF_RESULT_PASS) {
313 }
314 }
315
316 /*
317 * If the result is something like 'neutral', you probably
318 * want to accept the email anyway, just like you would
319 * when SPF_result() returns 'neutral'.
320 *
321 * It is possible that you will completely ignore the results
322 * until the SMPT DATA command.
323 */
324
325 if ( opt_debug > 0 ) {
326 printf ( "result = %s (%d)\n",
327 SPF_strresult(SPF_response_result(spf_response)),
328 SPF_response_result(spf_response));
329 printf ( "err = %s (%d)\n",
330 SPF_strerror(SPF_response_errcode(spf_response)),
331 SPF_response_errcode(spf_response));
332 for (i = 0; i < SPF_response_messages(spf_response); i++) {
333 SPF_error_t *err = SPF_response_message(spf_response, i);
334 printf ( "%s_msg = (%d) %s\n",
335 (SPF_error_errorp(err) ? "warn" : "err"),
336 SPF_error_code(err),
337 SPF_error_message(err));
338 }
339 }
340
341 #define VALID_STR(x) (x ? x : "")
342
343 printf( "%s\n%s\n%s\n%s\n",
344 SPF_strresult( SPF_response_result(spf_response) ),
345 VALID_STR(SPF_response_get_smtp_comment(spf_response)),
346 VALID_STR(SPF_response_get_header_comment(spf_response)),
347 VALID_STR(SPF_response_get_received_spf(spf_response))
348 );
349
350 res = SPF_response_result(spf_response);
351
352
353 /*
354 * The response from the SPF check contains malloced data, so
355 * make sure we free it.
356 */
357
358 SPF_response_free(spf_response);
359 if (spf_response_2mx)
360 SPF_response_free(spf_response_2mx);
361
362 error:
363
364 /*
365 * the SPF configuration variables contain malloced data, so we
366 * have to vfree them also.
367 */
368
369 if (spf_request)
370 SPF_request_free(spf_request);
371 if (spf_server)
372 SPF_server_free(spf_server);
373 return res;
374 }