/*
* Reaver - Command line processing functions
* Copyright (c) 2011, Tactical Network Solutions, Craig Heffner <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. * If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. * If you
* do not wish to do so, delete this exception statement from your
* version. * If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
#include <stdio.h>
#include <getopt.h>
#include <ctype.h>
#include <fcntl.h>
#include "globule.h"
#include "defs.h"
#include "iface.h"
#include "argsparser.h"
#include "pixie.h"
#include "misc.h"
/* Processes Reaver command line options */
int process_arguments(int argc, char **argv)
{
int ret_val = EXIT_SUCCESS;
int c = 0, channel = 0;
int long_opt_index = 0;
char bssid[MAC_ADDR_LEN] = { 0 };
char mac[MAC_ADDR_LEN] = { 0 };
char *short_options = "b:e:m:i:t:d:c:T:x:r:g:l:p:s:C:O:KZA5ELfnqvDShwN6JFu";
struct option long_options[] = {
{ "pixie-dust", no_argument, NULL, 'K' },
{ "interface", required_argument, NULL, 'i' },
{ "bssid", required_argument, NULL, 'b' },
{ "essid", required_argument, NULL, 'e' },
{ "mac", required_argument, NULL, 'm' },
{ "timeout", required_argument, NULL, 't' },
{ "m57-timeout", required_argument, NULL, 'T' },
{ "delay", required_argument, NULL, 'd' },
{ "lock-delay", required_argument, NULL, 'l' },
{ "fail-wait", required_argument, NULL, 'x' },
{ "channel", required_argument, NULL, 'c' },
{ "session", required_argument, NULL, 's' },
{ "recurring-delay", required_argument, NULL, 'r' },
{ "max-attempts", required_argument, NULL, 'g' },
{ "pin", required_argument, NULL, 'p' },
{ "exec", required_argument, NULL, 'C' },
{ "no-associate", no_argument, NULL, 'A' },
{ "ignore-locks", no_argument, NULL, 'L' },
{ "no-nacks", no_argument, NULL, 'N' },
{ "eap-terminate", no_argument, NULL, 'E' },
{ "dh-small", no_argument, NULL, 'S' },
{ "fixed", no_argument, NULL, 'f' },
{ "5ghz", no_argument, NULL, '5' },
{ "repeat-m6", no_argument, NULL, '6' },
{ "nack", no_argument, NULL, 'n' },
{ "quiet", no_argument, NULL, 'q' },
{ "verbose", no_argument, NULL, 'v' },
{ "win7", no_argument, NULL, 'w' },
{ "help", no_argument, NULL, 'h' },
{ "timeout-is-nack", no_argument, NULL, 'J' },
{ "ignore-fcs", no_argument, NULL, 'F' },
{ "output-file", required_argument, NULL, 'O'},
{ 0, 0, 0, 0 }
};
set_output_fd(-1);
/* Since this function may be called multiple times, be sure to set opt index to 0 each time */
optind = 0;
while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1)
{
switch(c)
{
case 'O':
{
int ofd = open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0660);
set_output_fd(ofd);
if(ofd == -1) perror("open outputfile failed: ");
}
break;
case 'Z':
case 'K':
pixie.do_pixie = 1;
set_max_pin_attempts(1);
break;
case 'u':
pixie.use_uptime = 1;
break;
case 'i':
set_iface(optarg);
break;
case 'b':
str2mac(optarg, (unsigned char *) &bssid);
set_bssid((unsigned char *) &bssid);
break;
case 'e':
set_ssid(optarg);
break;
case 'm':
str2mac(optarg, (unsigned char *) &mac);
set_mac((unsigned char *) &mac);
break;
case 't':
set_rx_timeout(atoi(optarg));
break;
case 'T':
set_m57_timeout(strtof(optarg, NULL) * SEC_TO_US);
break;
case 'c':
channel = strtod(optarg, NULL);
set_fixed_channel(1);
break;
case '5':
set_wifi_band(AN_BAND);
break;
case '6':
set_repeat_m6(1);
break;
case 'd':
set_delay(atoi(optarg));
break;
case 'l':
set_lock_delay(atoi(optarg));
break;
case 'p':
parse_static_pin(optarg);
set_max_pin_attempts(1);
break;
case 's':
set_session(optarg);
break;
case 'C':
set_exec_string(optarg);
break;
case 'A':
set_external_association(1);
break;
case 'L':
set_ignore_locks(1);
break;
case 'x':
set_fail_delay(atoi(optarg));
break;
case 'r':
parse_recurring_delay(optarg);
break;
case 'g':
set_max_pin_attempts(atoi(optarg));
break;
case 'E':
set_eap_terminate(1);
break;
case 'S':
set_dh_small(1);
break;
case 'n':
cprintf(INFO, "[+] ignoring obsolete -n switch\n");
break;
case 'J':
set_timeout_is_nack(1);
break;
case 'f':
set_fixed_channel(1);
break;
case 'v':
set_debug(get_debug() + 1);
break;
case 'q':
set_debug(CRITICAL);
break;
case 'w':
set_win7_compat(1);
break;
case 'N':
set_oo_send_nack(0);
break;
case 'F':
set_validate_fcs(0);
break;
default:
ret_val = EXIT_FAILURE;
}
}
if(channel)
{
change_channel(channel);
}
return ret_val;
}
/* Initialize some basic config settings */
void init_default_settings(void)
{
set_log_file(stdout);
set_max_pin_attempts(P1_SIZE + P2_SIZE);
set_delay(DEFAULT_DELAY);
set_lock_delay(DEFAULT_LOCK_DELAY);
set_debug(INFO);
set_auto_channel_select(1);
set_timeout_is_nack(0);
set_oo_send_nack(1);
set_wifi_band(BG_BAND);
set_validate_fcs(1);
pixie.do_pixie = 0;
set_pin_string_mode(0);
}
/* Parses the recurring delay optarg */
void parse_recurring_delay(char *arg)
{
char *x = NULL, *y = NULL;
x = strdup(arg);
y = strchr(x, ':');
if(y)
{
memset(y, 0, 1);
y++;
set_recurring_delay_count(atoi(x));
set_recurring_delay(atoi(y));
}
free(x);
}
int is_valid_pin(char *pin)
{
if(!pin)
return 0;
int i;
for (i = 0; i < strlen(pin); i++)
{
if(!isdigit(pin[i]))
return 0;
}
if(strlen(pin) == 8)
{
char pin7[8] = { 0 };
char pin8[9] = { 0 };
memcpy((void *) &pin7, pin, sizeof(pin7)-1);
snprintf(pin8, 9, "%s%d", pin7, wps_pin_checksum(atoi(pin7)));
if (strcmp(pin, pin8) != 0)
return 0;
}
return 1;
}
/* Parse the WPS pin to use into p1 and p2 */
void parse_static_pin(char *pin)
{
int len = 0;
char p1[5] = { 0 };
char p2[4] = { 0 };
len = strlen(pin);
if((len == 4 || len == 7 || len == 8) && is_valid_pin(pin) != 0)
{
memcpy((void *) &p1, pin, sizeof(p1)-1);
set_static_p1((char *) &p1);
if(len > 4)
{
memcpy((void *) &p2, pin+sizeof(p1)-1, sizeof(p2)-1);
set_static_p2((char *) &p2);
}
}
else
{
set_pin_string_mode(1);
set_static_p1(pin);
}
}