001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    package org.apache.james.jspf.impl;
021    
022    import org.apache.commons.cli.CommandLine;
023    import org.apache.commons.cli.CommandLineParser;
024    import org.apache.commons.cli.HelpFormatter;
025    import org.apache.commons.cli.OptionBuilder;
026    import org.apache.commons.cli.Options;
027    import org.apache.commons.cli.ParseException;
028    import org.apache.commons.cli.PosixParser;
029    import org.apache.james.jspf.core.exceptions.SPFErrorConstants;
030    import org.apache.james.jspf.executor.SPFResult;
031    import org.apache.log4j.ConsoleAppender;
032    import org.apache.log4j.Level;
033    import org.apache.log4j.Logger;
034    import org.apache.log4j.SimpleLayout;
035    
036    /**
037     * This class is used for commandline usage of JSPF
038     * 
039     */
040    public class SPFQuery {
041    
042        private final static int PASS_RCODE = 0;
043    
044        private final static int FAIL_RCODE = 1;
045    
046        private final static int SOFTFAIL_RCODE = 2;
047    
048        private final static int NEUTRAL_RCODE = 3;
049    
050        private final static int TEMP_ERROR_RCODE = 4;
051    
052        private final static int PERM_ERROR_RCODE = 5;
053    
054        private final static int NONE_RCODE = 6;
055    
056        private final static int UNKNOWN_RCODE = 255;
057    
058        private final static String CMD_IP = "ip";
059        private final static char CHAR_IP = 'i';
060    
061        private final static String CMD_SENDER = "sender";
062        private final static char CHAR_SENDER = 's';
063    
064        private final static String CMD_HELO = "helo";
065        private final static char CHAR_HELO = 'h';
066    
067        private final static String CMD_DEBUG = "debug";
068        private final static char CHAR_DEBUG = 'd';
069    
070        private final static String CMD_VERBOSE = "verbose";
071        private final static char CHAR_VERBOSE = 'v';
072    
073        private final static String CMD_DEFAULT_EXP = "default-explanation";
074        private final static char CHAR_DEFAULT_EXP = 'e';
075    
076        private final static String CMD_BEST_GUESS = "enable-best-guess";
077        private final static char CHAR_BEST_GUESS = 'b';
078        
079        private final static String CMD_TRUSTED_FORWARDER = "enable-trusted-forwarder";
080        private final static char CHAR_TRUSTED_FORWARDER = 't';
081    
082        private static Logger logger = Logger.getRootLogger();
083    
084        /**
085         * @param args
086         *            The commandline arguments to parse
087         */
088        public static void main(String[] args) {
089    
090            String ip = null;
091            String sender = null;
092            String helo = null;
093            String defaultExplanation = null;
094            boolean useBestGuess = false;
095            boolean useTrustedForwarder = false;
096    
097            SimpleLayout layout = new SimpleLayout();
098            ConsoleAppender consoleAppender = new ConsoleAppender(layout);
099            logger.addAppender(consoleAppender);
100    
101            logger.setLevel(Level.ERROR);
102    
103            Options options = generateOptions();
104            CommandLineParser parser = new PosixParser();
105    
106            try {
107                CommandLine line = parser.parse(options, args);
108    
109                ip = line.getOptionValue(CHAR_IP);
110                sender = line.getOptionValue(CHAR_SENDER);
111                helo = line.getOptionValue(CHAR_HELO);
112                defaultExplanation = line.getOptionValue(CHAR_DEFAULT_EXP);
113                useBestGuess = line.hasOption(CHAR_BEST_GUESS);
114                useTrustedForwarder = line.hasOption(CHAR_TRUSTED_FORWARDER);
115                // check if all needed values was set
116                if (ip != null && sender != null && helo != null) {
117    
118                    if (line.hasOption(CHAR_DEBUG))
119                        logger.setLevel(Level.DEBUG);
120                    if (line.hasOption(CHAR_VERBOSE))
121                        logger.setLevel(Level.TRACE);
122    
123                    SPF spf = new DefaultSPF(new Log4JLogger(logger));
124    
125                    // Check if we should set a costum default explanation
126                    if (defaultExplanation != null) {
127                        spf.setDefaultExplanation(defaultExplanation);
128                    }
129    
130                    // Check if we should use best guess
131                    if (useBestGuess == true) {
132                        spf.setUseBestGuess(true);
133                    }
134                    
135                    if (useTrustedForwarder == true) {
136                        spf.setUseTrustedForwarder(true);
137                    }
138    
139                    SPFResult result = spf.checkSPF(ip, sender, helo);
140                    System.out.println(result.getResult());
141                    System.out.println(result.getHeader());
142                    System.exit(getReturnCode(result.getResult()));
143    
144                } else {
145                    usage();
146                }
147            } catch (ParseException e) {
148                usage();
149            }
150        }
151    
152        /**
153         * Return the generated Options
154         * 
155         * @return options
156         */
157        private static Options generateOptions() {
158            Options options = new Options();
159            
160            OptionBuilder.withLongOpt(CMD_IP);
161            OptionBuilder.withValueSeparator('=');
162            OptionBuilder.withArgName("ip");
163            OptionBuilder.withDescription("Sender IP address");
164            OptionBuilder.isRequired();
165            OptionBuilder.hasArg();
166            options.addOption(OptionBuilder.create(CHAR_IP));
167           
168            
169            OptionBuilder.withLongOpt(CMD_SENDER);
170            OptionBuilder.withValueSeparator('=');
171            OptionBuilder.withArgName("sender");
172            OptionBuilder.withDescription("Sender address");
173            OptionBuilder.isRequired();
174            OptionBuilder.hasArg();
175            options.addOption(OptionBuilder.create(CHAR_SENDER));
176            
177            OptionBuilder.withLongOpt(CMD_HELO);
178            OptionBuilder.withValueSeparator('=');
179            OptionBuilder.withArgName("helo");
180            OptionBuilder.withDescription("Helo name");
181            OptionBuilder.isRequired();
182            OptionBuilder.hasArg();
183            options.addOption(OptionBuilder.create(CHAR_HELO));
184                    
185            OptionBuilder.withLongOpt(CMD_DEFAULT_EXP);
186            OptionBuilder.withValueSeparator('=');
187            OptionBuilder.withArgName("expl");
188            OptionBuilder.withDescription("Default explanation");
189            OptionBuilder.hasArg();  
190            options.addOption(OptionBuilder.create(CHAR_DEFAULT_EXP));
191                    
192            OptionBuilder.withLongOpt(CMD_BEST_GUESS);
193            OptionBuilder.withArgName("bestguess");
194            OptionBuilder.withDescription("Enable 'best guess' rule");
195            options.addOption(OptionBuilder.create(CHAR_BEST_GUESS));
196                   
197            OptionBuilder.withLongOpt(CMD_TRUSTED_FORWARDER);
198            OptionBuilder.withArgName("trustedfwd");
199            OptionBuilder.withDescription("Enable 'trusted forwarder' rule");
200            options.addOption(OptionBuilder.create(CHAR_TRUSTED_FORWARDER));
201    
202            OptionBuilder.withLongOpt(CMD_DEBUG);
203            OptionBuilder.withArgName("debug");
204            OptionBuilder.withDescription("Enable debug");
205            options.addOption(OptionBuilder.create(CHAR_DEBUG));
206    
207            OptionBuilder.withLongOpt(CMD_VERBOSE);
208            OptionBuilder.withArgName("verbose");
209            OptionBuilder.withDescription("Enable verbose mode");
210            options.addOption(OptionBuilder.create(CHAR_VERBOSE));
211                    
212            return options;
213        }
214    
215        /**
216         * Print out the usage
217         */
218        private static void usage() {
219            HelpFormatter hf = new HelpFormatter();
220            hf.printHelp("SPFQuery", generateOptions(), true);
221            System.exit(UNKNOWN_RCODE);
222        }
223    
224        /**
225         * Return the return code for the result
226         * 
227         * @param result
228         *            The result
229         * @return returnCode
230         */
231        private static int getReturnCode(String result) {
232    
233            if (result.equals(SPFErrorConstants.PASS_CONV)) {
234                return PASS_RCODE;
235            } else if (result.equals(SPFErrorConstants.FAIL_CONV)) {
236                return FAIL_RCODE;
237            } else if (result.equals(SPFErrorConstants.SOFTFAIL_CONV)) {
238                return SOFTFAIL_RCODE;
239            } else if (result.equals(SPFErrorConstants.NEUTRAL_CONV)) {
240                return NEUTRAL_RCODE;
241            } else if (result.equals(SPFErrorConstants.TEMP_ERROR_CONV)) {
242                return TEMP_ERROR_RCODE;
243            } else if (result.equals(SPFErrorConstants.PERM_ERROR_CONV)) {
244                return PERM_ERROR_RCODE;
245            } else if (result.equals(SPFErrorConstants.NONE_CONV)) {
246                return NONE_RCODE;
247            }
248    
249            return UNKNOWN_RCODE;
250        }
251    
252    }