/*
 *	Firebird Support - by David Maciejak @ GMAIL dot com
 *	
 *	you need to pass full path to the fdb file as OPT
 */

#include "hydra-mod.h"

#ifndef LIBFIREBIRD
void
dummy_firebird()
{
  printf("\n");
}
#else

#include <stdio.h>
#include <ibase.h>

#define DEFAULT_DB "C:\\Program Files\\Firebird\\Firebird_2_0\\security2.fdb"

extern char *HYDRA_EXIT;

int
start_firebird(int s, unsigned long int ip, int port, unsigned char options, char *miscptr, FILE * fp)
{
    char *empty = "";
    char *login, *pass;
    char database[256];
    char connection_string[1024];
    struct in_addr remote_ip;

    isc_db_handle   db = NULL;      /* database handle */
    ISC_STATUS_ARRAY status;         /* status vector */

    char *  dpb = NULL,    /* DB parameter buffer */
                    *d, *p;

    short           dpb_length = 0;
    long            l,sweep_interval = 16384;

    if(miscptr)
        strncpy(database,miscptr,sizeof(database));
    else
        strncpy(database,DEFAULT_DB,sizeof(database));
        
    remote_ip.s_addr = ip;
    
    
	if (strlen(login = hydra_get_next_login()) == 0)
		login = empty;
	if (strlen(pass = hydra_get_next_password()) == 0)
		pass = empty;

  dpb = (char *) malloc(7);
    p = dpb;
    *p++ = '\1';
    *p++ = isc_dpb_sweep_interval;
    *p++ = '\4';
    l = isc_vax_integer((char *) &sweep_interval, 4);
    d = (char *) &l;
    *p++ = *d++;
    *p++ = *d++;
    *p++ = *d++;
    *p = *d;
    dpb_length = 7;

    /* Add user and password to dpb */
    isc_expand_dpb(&dpb, (short *) &dpb_length,
                   isc_dpb_user_name, login,
                   isc_dpb_password, pass,  NULL);

    /* Create connection string */
    snprintf(connection_string, sizeof(connection_string), "%s:%s", inet_ntoa(remote_ip), database);

    	if (isc_attach_database(status, 0, connection_string, &db, dpb_length, dpb))
	{
		/* for debugging perpose */
		//isc_print_status(status);
        	hydra_completed_pair();
        	if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
            		return 2;    
	}
	else {
		isc_detach_database(status, &db);
		isc_free(dpb);
		hydra_report_found_host(port, ip, "firebird", fp);
		hydra_completed_pair();
		if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
			return 3;
		return 2;
	}
    return 1;
}

void
service_firebird(unsigned long int ip, int sp, unsigned char options, char *miscptr, FILE *fp, int port)
{
	int run = 1, next_run, sock = -1;
	int myport = PORT_FIREBIRD, mysslport = PORT_FIREBIRD_SSL;

	hydra_register_socket(sp);
	if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
		return;
	
	while (1)
	{

		switch (run)
		{
			case 1:                    /* connect and service init function */
				if (sock >= 0)
					sock = hydra_disconnect(sock);
				if ((options & OPTION_SSL) == 0) 
				{
					if (port != 0)
						myport = port;
					sock = hydra_connect_tcp(ip, myport);
					port = myport;
				} else {
					if (port != 0)
						mysslport = port;
					sock = hydra_connect_ssl(ip, mysslport);
					port = mysslport;
				}
				if (sock < 0)
				{
					fprintf(stderr, "Error: Child with pid %d terminating, can not connect\n", (int) getpid());
					hydra_child_exit(1);
				}
				
				next_run = 2;
				break;

			case 2:
      
      				/*
      				 *	Here we start the password cracking process  
				     */
                
				next_run = start_firebird(sock, ip, port, options, miscptr, fp);
				break;
			case 3:
				
				if (sock >= 0)
					sock = hydra_disconnect(sock);
				hydra_child_exit(0);
				return;
		
			default:
			
				fprintf(stderr, "Caught unknown return code, exiting!\n");
				hydra_child_exit(0);
				exit(-1);
		}
		run = next_run;
	}
}

#endif
