// throw some statistics about the db to stdout.
// if precise!=0 the stats will be queried nail by nail which can be slow
void show_stats(sqlite3* db, int precise) {

	sql_exec(db,"BEGIN;");

	int essids = query_int(db, "SELECT COUNT(*) FROM essid;");
	int passwds = query_int(db,"SELECT COUNT(*) FROM passwd;");
	int done;
	if (precise != 0) {
		printf("Determining precise statistics may be slow...\n");
		done = query_int(db, "SELECT COUNT(*) FROM essid,passwd INNER JOIN pmk ON pmk.essid_id = essid.essid_id AND pmk.passwd_id = passwd.passwd_id");
	} else {
		done = query_int(db, "SELECT COUNT(*) FROM pmk;");
	}
	fprintf(stdout,"There are %i ESSIDs and %i passwords in the database. %i out of %i possible combinations have been computed (%g%%).\n\n", essids, passwds, done, essids*passwds, essids*passwds > 0 ? ((double)done*100)/(essids*passwds) : 0);

	if (precise != 0) {
		sql_stdout(db, "select essid.essid AS ESSID, essid.prio AS Priority, round(count(pmk.essid_id) * 100.0 / count(*),2) AS Done from essid,passwd left join pmk on pmk.essid_id = essid.essid_id and pmk.passwd_id = passwd.passwd_id group by essid.essid_id;",0);
	} else {
		sql_stdout(db, "SELECT essid.essid AS ESSID, essid.prio AS Priority, ROUND(COUNT(pmk.essid_id) * 100.0 / (SELECT COUNT(*) FROM passwd),2) AS Done FROM essid LEFT JOIN pmk ON pmk.essid_id = essid.essid_id GROUP BY essid.essid_id;",0);
	}

	sql_exec(db,"COMMIT;");

}
// export to a cowpatty file
void export_cowpatty(sqlite3* db, char* essid, char* filename) {
	struct hashdb_head filehead;
	memset(&filehead, 0, sizeof(filehead));
	FILE *f = NULL;

	if (access(filename, F_OK)==0) {
		printf("The file already exists and I won't overwrite it.\n");
		return;
	}

	// ensure that the essid is found in the db and has at least one entry in the pmk table.
	char *sql = sqlite3_mprintf("SELECT COUNT(*) FROM (SELECT passwd, pmk FROM essid,passwd INNER JOIN pmk ON pmk.passwd_id = passwd.passwd_id AND pmk.essid_id = essid.essid_id WHERE essid.essid = '%q' LIMIT 1);",essid);
	int rc = query_int(db,sql);
	sqlite3_free(sql);
	if (rc == 0) {
		printf("There is no such ESSID in the database or there are no PMKs for it.\n");
		return;
	}

	memcpy(filehead.ssid, essid,strlen(essid));
	filehead.ssidlen = strlen(essid);
	filehead.magic = GENPMKMAGIC;

	f = fopen(filename, "w");
	if (f == NULL || fwrite(&filehead, sizeof(filehead), 1, f) != 1) {
		printf("Couldn't open the export file for writing.\n");
		return;
	}

	// as we have an open filehandle, we now query the db to return passwds and associated PMKs for that essid. we pass the filehandle to a callback function which will write the rows to the file.
	sql = sqlite3_mprintf("SELECT passwd, pmk FROM essid,passwd INNER JOIN pmk ON pmk.passwd_id = passwd.passwd_id AND pmk.essid_id = essid.essid_id WHERE essid.essid = '%q'",essid);
	printf("Exporting...\n");
	rc = sql_exec_cb(db,sql,&sql_exportcow,f);
	sqlite3_free(sql);
	if (rc != SQLITE_OK) {
		printf("There was an error while exporting.\n");
	}

	fclose(f);
	printf("Done.\n");
}
// import a cowpatty file
int import_cowpatty(sqlite3* db, char* filename) {
	struct hashdb_head filehead;
	struct hashdb_rec rec;
	FILE *f = NULL;
	int rc;
	sqlite3_stmt *stmt;
	char* sql;
	int essid_id;
	int wordlength;
	char passwd[63+1];

	if (strcmp(filename,"-") == 0) {
		f = stdin;
	} else {
		f = fopen(filename, "r");
	}
	if (f == NULL || fread(&filehead, sizeof(filehead),1,f) != 1) {
		printf("Couldn't open the import file for reading.\n");
		return 0;
	} else if (filehead.magic != GENPMKMAGIC) {
		printf("File doesn't seem to be a cowpatty file.\n");
		fclose(f);
		return 0;
	} else if (verify_essid((char *)filehead.ssid) != 0) {
		printf("The file's ESSID is invalid.\n");
		fclose(f);
		return 0;
	}

	printf("Reading header...\n");

	//We need protection so concurrent transactions can't smash the ID-references
	sql_exec(db,"BEGIN;");

	sql = sqlite3_mprintf("INSERT OR IGNORE INTO essid (essid) VALUES ('%q');",filehead.ssid);
	sql_exec(db,sql);
	sqlite3_free(sql);

	//since there is only one essid per file, we can determine it's ID now
	sql = sqlite3_mprintf("SELECT essid_id FROM essid WHERE essid = '%q'", filehead.ssid);
	essid_id = query_int(db,sql);
	sqlite3_free(sql);
	if (essid_id == 0) {
		fclose(f);
		sql_exec(db,"ROLLBACK;");
		printf("ESSID couldn't be inserted. I've given up.\n");
		return 0;
	}

	sql = sqlite3_mprintf("CREATE TEMPORARY TABLE import (passwd text, pmk blob);", essid_id);
	sql_exec(db,sql);
	sqlite3_free(sql);
	sql_prepare(db,"INSERT INTO import (passwd,pmk) VALUES (@pw,@pmk)",&stmt,-1);

	printf("Reading...\n");
	while ((rc = fread(&rec.rec_size, sizeof(rec.rec_size), 1, f)) == 1) {
		wordlength = abs(rec.rec_size) - (sizeof(rec.pmk) + sizeof(rec.rec_size));
		//prevent out of bounds writing (sigsegv guaranteed) but don't skip the whole file if wordlength < 8
		if (wordlength > 0 && wordlength < (int) sizeof(passwd)) {
			passwd[wordlength] = 0;
			rc += fread(passwd, wordlength, 1, f);
			if (rc == 2) rc += fread(&rec.pmk, sizeof(rec.pmk), 1, f);
		}
		if (rc != 3) {
			fprintf(stdout,"Error while reading record (%i).\n",rc);
			sqlite3_finalize(stmt);
			if (db == NULL) {
				printf("omg");
				fflush(stdout);
			}
			sql_exec(db, "ROLLBACK;");
			fclose(f);
			return 1;
		}

		if (verify_passwd(passwd) == 0) {
			sqlite3_bind_text(stmt,1,passwd, strlen(passwd),SQLITE_TRANSIENT);
			sqlite3_bind_blob(stmt,2,&rec.pmk, sizeof(rec.pmk),SQLITE_TRANSIENT);
			if (sql_step(stmt,-1) == SQLITE_DONE) {
				sqlite3_reset(stmt);
			} else {
				printf("Error while inserting record into database.\n");
				sqlite3_finalize(stmt);
				sql_exec(db, "ROLLBACK;");
				fclose(f);
				return 1;
			}
		} else {
			fprintf(stdout,"Invalid password %s will not be imported.\n",passwd);
		}
	}
	sqlite3_finalize(stmt);

	if (!feof(f)) {
		printf("Error while reading file.\n");
		sql_exec(db,"ROLLBACK;");
		fclose(f);
		return 1;
	}

	printf("Updating references...\n");
	sql_exec(db, "INSERT OR IGNORE INTO passwd (passwd) SELECT passwd FROM import;");

	//TODO Give the user a choice to either INSERT OR UPDATE or INSERT OR IGNORE
	printf("Writing...\n");
	sql = sqlite3_mprintf("INSERT OR IGNORE INTO pmk (essid_id,passwd_id,pmk) SELECT %i,passwd.passwd_id,import.pmk FROM import INNER JOIN passwd ON passwd.passwd = import.passwd;",essid_id);
	sql_exec(db,sql);
	sqlite3_free(sql);

	sql_exec(db,"COMMIT;");

	fclose(f);
	return 1;
}
/*
batch-process all combinations of ESSIDs and PASSWDs. this function may be called
only once per db at the same time, yet multiple processes can batch-process a single db.
don't modify this function's layout or it's queries without carefully considering speed, efficiency and concurrency.
*/
void batch_process(sqlite3* db) {
	int rc;
	int cur_essid = 0;
	struct timeval starttime;
	struct timeval curtime;
	gettimeofday(&starttime,NULL);
	int rowcount = 0;
	char *sql;

	if (sql_exec(db, "CREATE TEMPORARY TABLE temp.buffer (wb_id integer, essid_id integer, passwd_id integer, essid text, passwd text, pmk blob);") != SQLITE_OK) {
		fprintf(stderr,"Failed to create buffer for batch processing.\n");
		return;
	}

	// may fail - thats ok
	cur_essid = query_int(db,"SELECT essid_id FROM workbench LIMIT 1;");


	while(1) {
		//loop over everything
		do {
			//loop over ESSID
			do {
				//loop over workbench
				sql_exec(db,"DELETE FROM temp.buffer;");
				// select some work from the workbench into our own buffer
				// move lockid ahead so other clients won't get those rows any time soon
				sql_exec(db,"BEGIN EXCLUSIVE;");
				sql_exec(db,"INSERT INTO temp.buffer (wb_id,essid_id,passwd_id,essid,passwd) SELECT wb_id, essid.essid_id,passwd.passwd_id,essid,passwd FROM workbench CROSS JOIN essid ON essid.essid_id = workbench.essid_id CROSS JOIN passwd ON passwd.passwd_id = workbench.passwd_id ORDER BY lockid LIMIT 25000;");
				sql_exec(db,"UPDATE workbench SET lockid=lockid+1 WHERE wb_id IN (SELECT wb_id FROM buffer);");
				sql_exec(db,"COMMIT;");

				rc = query_int(db,"SELECT COUNT(*) FROM buffer;");
				if (rc > 0) {
					// now calculate all the PMKs with a single statement.
					// remember the update won't lock the db
					sql_exec(db,"UPDATE temp.buffer SET pmk = PMK(essid,passwd);");

					// commit work and delete package from workbench
					sql_exec(db,"BEGIN EXCLUSIVE;");
					sql_exec(db,"INSERT OR IGNORE INTO pmk (essid_id,passwd_id,pmk) SELECT essid_id,passwd_id,pmk FROM temp.buffer");
					sql_exec(db,"DELETE FROM workbench WHERE wb_id IN (SELECT wb_id FROM buffer);");
					sql_exec(db,"COMMIT;");

					rowcount += rc;
					gettimeofday(&curtime,NULL);
					int timediff = curtime.tv_sec - starttime.tv_sec;
					fprintf(stdout,"\rComputed %i PMK in %i seconds (%i PMK/s, %i in buffer). ",rowcount,timediff, timediff > 0 ? rowcount / timediff : rowcount, query_int(db,"SELECT COUNT(*) FROM workbench;"));
					fflush(stdout);
				}
			} while (rc > 0);
			sql = sqlite3_mprintf("INSERT OR IGNORE INTO workbench (essid_id,passwd_id) SELECT essid.essid_id,passwd.passwd_id FROM passwd CROSS JOIN essid LEFT JOIN pmk ON pmk.essid_id = essid.essid_id AND pmk.passwd_id = passwd.passwd_id WHERE essid.essid_id = %i AND pmk.essid_id IS NULL LIMIT 250000;",cur_essid);
			sql_exec(db,sql);
			sqlite3_free(sql);
		} while (query_int(db,"SELECT COUNT(*) FROM workbench INNER JOIN essid ON essid.essid_id = workbench.essid_id INNER JOIN passwd ON passwd.passwd_id = workbench.passwd_id;") > 0);

		cur_essid = query_int(db,"SELECT essid.essid_id FROM essid LEFT JOIN pmk USING (essid_id) WHERE VERIFY_ESSID(essid.essid) == 0 GROUP BY essid.essid_id HAVING COUNT(pmk.essid_id) < (SELECT COUNT(*) FROM passwd) ORDER BY essid.prio,COUNT(pmk.essid_id),RANDOM() LIMIT 1;");
		if (cur_essid == 0) {
			printf("All ESSID processed.\n\n");
			sqlite3_close(db);
			exit(0);
			/*
			printf("No free ESSID found. Will try determining new ESSID in 5 minutes...\n");
			sleep(60*5);
			// slower, yet certain. should never be any better than the above, unless users fumble with the db.
			cur_essid = query_int(db,"SELECT essid.essid_id FROM essid,passwd LEFT JOIN pmk ON pmk.essid_id = essid.essid_id AND pmk.passwd_id = passwd.passwd_id WHERE pmk.essid_id IS NULL LIMIT 1;");
			if (cur_essid == 0) {
				printf("No free ESSID found. Sleeping 25 additional minutes...\n");
				sleep(60*25);
			}
			*/
		}
	}

	//never reached
	sql_exec(db,"DROP TABLE temp.buffer;");
}
Example #5
0
static int procfs_read_encr(char *page, char **start, off_t off,
			    int count, int *eof, void *data)
{
	char *p = page;
	struct ndis_handle *handle = (struct ndis_handle *) data;
	int i, encr_status, auth_mode, op_mode;
	unsigned int res, written, needed;
	struct ndis_essid essid;
	mac_address ap_address;

	if (off != 0) {
		*eof = 1;
		return 0;
	}

	res = doquery(handle, NDIS_OID_BSSID, (char*)&ap_address,
		      sizeof(ap_address), &written, &needed);
	if (res)
		memset(ap_address, 0, ETH_ALEN);
	p += sprintf(p, "ap_address=%2.2X", ap_address[0]);
	for (i = 1 ; i < ETH_ALEN ; i++)
		p += sprintf(p, ":%2.2X", ap_address[i]);
	p += sprintf(p, "\n");

	res = doquery(handle, NDIS_OID_ESSID, (char*)&essid,
		      sizeof(essid), &written, &needed);
	if (!res)
	{
		essid.essid[essid.length] = '\0';
		p += sprintf(p, "essid=%s\n", essid.essid);
	}

	res = query_int(handle, NDIS_OID_ENCR_STATUS, &encr_status);
	res |= query_int(handle, NDIS_OID_AUTH_MODE, &auth_mode);

	if (!res)
	{
		int active = handle->encr_info.active;
		p += sprintf(p, "tx_key=%u\n", handle->encr_info.active);
		p += sprintf(p, "key=");
		if (handle->encr_info.keys[active].length > 0)
			for (i = 0; i < NDIS_ENCODING_TOKEN_MAX &&
				     i < handle->encr_info.keys[active].length;
			     i++)
				p += sprintf(p, "%2.2X",
					     handle->encr_info.keys[active].key[i]);
		else
			p += sprintf(p, "off");
		p += sprintf(p, "\n");

		p += sprintf(p, "status=%sabled\n",
			     (encr_status == ENCR_DISABLED) ? "dis" : "en");
		p += sprintf(p, "auth_mode=%s\n",
			     (auth_mode == AUTHMODE_RESTRICTED) ?
			     "restricted" : "open");
	}

	res = query_int(handle, NDIS_OID_MODE, &op_mode);
	p += sprintf(p, "mode=%s\n", (op_mode == NDIS_MODE_ADHOC) ?
		     "adhoc" : (op_mode == NDIS_MODE_INFRA) ?
		     "managed" : "auto");
	if (p - page > count)
	{
		WARNING("wrote %u bytes (limit is %u)", p - page, count);
		*eof = 1;
	}

	return (p - page);
}
Example #6
0
static int procfs_read_hw(char *page, char **start, off_t off,
			  int count, int *eof, void *data)
{
	char *p = page;
	struct ndis_handle *handle = (struct ndis_handle *)data;
	struct ndis_configuration config;
	unsigned int res, written, needed, power_mode;
	unsigned long tx_power, bit_rate, rts_threshold, frag_threshold;
	unsigned long antenna;

	if (off != 0) {
		*eof = 1;
		return 0;
	}

	res = doquery(handle, NDIS_OID_CONFIGURATION,
		      (char*)&config, sizeof(config), &written, &needed);
	if (!res)
	{
		p += sprintf(p, "beacon_period=%u msec\n",
			     config.beacon_period);
		p += sprintf(p, "atim_window=%u msec\n", config.atim_window);
		p += sprintf(p, "frequency=%u kHZ\n", config.ds_config);
		p += sprintf(p, "hop_pattern=%u\n",
			     config.fh_config.hop_pattern);
		p += sprintf(p, "hop_set=%u\n",
			     config.fh_config.hop_set);
		p += sprintf(p, "dwell_time=%u msec\n",
			     config.fh_config.dwell_time);
	}

	res = doquery(handle, NDIS_OID_TX_POWER_LEVEL, (char*)&tx_power,
		      sizeof(tx_power), &written, &needed);
	if (!res)
		p += sprintf(p, "tx_power=%lu mW\n", tx_power);

	res = doquery(handle, NDIS_OID_GEN_SPEED, (char*)&bit_rate,
		      sizeof(bit_rate), &written, &needed);
	if (!res)
		p += sprintf(p, "bit_rate=%lu kBps\n", bit_rate / 10);

	res = doquery(handle, NDIS_OID_RTS_THRESH, (char*)&rts_threshold,
		      sizeof(rts_threshold), &written, &needed);
	if (!res)
		p += sprintf(p, "rts_threshold=%lu bytes\n", rts_threshold);

	res = doquery(handle, NDIS_OID_FRAG_THRESH, (char*)&frag_threshold,
		      sizeof(frag_threshold), &written, &needed);
	if (!res)
		p += sprintf(p, "frag_threshold=%lu bytes\n", frag_threshold);

	res = query_int(handle, NDIS_OID_POWER_MODE, &power_mode);
	if (!res)
		p += sprintf(p, "power_mode=%s\n",
			     (power_mode == NDIS_POWER_OFF) ?
			     "always_on" :
			     (power_mode == NDIS_POWER_MAX) ?
			     "max_savings" : "min_savings");

	res = doquery(handle, NDIS_OID_NUM_ANTENNA, (char *)&antenna,
		      sizeof(antenna), &written, &needed);
	if (!res)
		p += sprintf(p, "num_antennas=%lu\n",
			     antenna);

	res = doquery(handle, NDIS_OID_TX_ANTENNA, (char *)&antenna,
		      sizeof(antenna), &written, &needed);
	if (!res)
		p += sprintf(p, "tx_antenna=%lu\n",
			     antenna);

	res = doquery(handle, NDIS_OID_RX_ANTENNA, (char *)&antenna,
		      sizeof(antenna), &written, &needed);
	if (!res)
		p += sprintf(p, "rx_antenna=%lu\n",
			     antenna);

	if (p - page > count)
	{
		WARNING("wrote %u bytes (limit is %u)", p - page, count);
		*eof = 1;
	}

	return (p - page);
}