/* doscan - Denial Of Service Capable Auditing of Networks * Copyright (C) 2003, 2005 Florian Weimer * * 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 */ #include "config.h" #include "opt.h" #include "proto.h" #include "results.h" #include "rx.h" #include "scan_trigger.h" #include "scan_tcp.h" #include #include #include #include #include #include #include #include #include static bool ident_start (subnets&); static void ident_open (scan_host_t *); void proto_ident_check_register (void) { proto_register ("ident_check", ident_start, ident_open); } static void ident_open (scan_host_t *) { } class proto_ident_check : public tcp_half_duplex_handler { unsigned local_port; static const rx regexp_response; public: proto_ident_check(event_queue&, ipv4_t); virtual void ready(int state, int error, const std::string& data); }; const rx proto_ident_check::regexp_response("^[ ]*(\\d+) *, *(\\d+) *" ": *(?:USERID|ERROR) *:", PCRE_CASELESS); proto_ident_check::proto_ident_check(event_queue& q, ipv4_t host) : tcp_half_duplex_handler(q, host, opt_port) { set_relative_timeout(opt_connect_timeout); } void proto_ident_check::ready(int state, int error, const std::string& data) { if (error && state > 0) { results_add(host(), error, "error after connect"); return; } switch (state) { case 0: // Just got connected. { // Check for pending connection error. Only record the error if // the connection has been reset. int error = get_error(); if (error) { if (error == ECONNRESET) { results_add(host(), error, "error during connect"); } return; } // Construct the reply. We need the port number on our side, so // we fetch it using getsockname(). struct sockaddr_in sa; socklen_t len = sizeof(sa); int result = getsockname(fd(), reinterpret_cast(&sa), &len); if (result == -1) { fprintf(stderr, "%s: getsockname() failed, error was: %s\n", opt_program, strerror(errno)); exit(EXIT_FAILURE); } local_port = htons(sa.sin_port); char request[50]; sprintf(request, "%u , %u\r\n", port(), local_port); send(state + 1, request); return; } case 1: // Process the reply. { unsigned len = data.size(); if (data.size() < 2) { request_more_data(state); return; } if (data[len - 2] != '\r' || data[len - 1] != '\n') { // Do not retrieve too much data. if (data.size() < 1000) { request_more_data(state); return; } else { results_add(host(), RESULTS_ERROR_NOMATCH, data); return; } } else { // We have at least a line terminated by CRLF. std::string::size_type pos = data.find("\r\n"); if (pos != len - 2) { // Multiple lines in reply. results_add(host(), RESULTS_ERROR_NOMATCH, data); return; } rx::matches matches; bool match = regexp_response.exec(data, matches); if (!match || (static_cast(atoi(matches[1].data().c_str())) != port()) || (static_cast(atoi(matches[2].data().c_str())) != local_port)) { results_add(host(), RESULTS_ERROR_NOMATCH, data); return; } // Reply is genuine, log only in verbose mode. if (opt_verbose) { results_add(host(), data); } return; } } } abort(); } static bool ident_start(subnets& n) { if (opt_receive && opt_receive[0]) { fprintf (stderr, "%s: --receive is not supported by this module\n", opt_program); exit (EXIT_FAILURE); } if (opt_banner_size) { fprintf (stderr, "%s: --banner is not supported by this module.\n", opt_program); exit (EXIT_FAILURE); } if (opt_send && (opt_send[0] != 0)) { fprintf (stderr, "%s: --send is not supported by this module.\n", opt_program); exit (EXIT_FAILURE); } std::auto_ptr q(event_queue::create(opt_fd_count)); scan_trigger::default_handler th; scan_trigger t(*q, n, th, opt_fd_count, opt_add_timeout, opt_add_burst); q->run(); return false; } // arch-tag: fd44b01d-9462-4e44-96d8-858740c66315