int sql_dump(char *query, char **str_fmt, int num_cols, FILE *fp) { sqlite3_stmt *stmt = NULL; int rc = 0, j = 0, count = 0; if(!query) { return 0; } /* Prepare the SQL query */ rc = sqlite3_prepare_v2(db,query,strlen(query),&stmt,NULL); if(rc != SQLITE_OK) { sql_log_error(); return 0; } /* Loop until the query has finished */ while(((rc = sqlite3_step(stmt)) != SQLITE_DONE)) { switch(rc) { case SQLITE_ERROR: sqlite3_finalize(stmt); sql_log_error(); return 0; case SQLITE_BUSY: /* If the table is locked, wait then try again */ usleep(BUSY_WAIT_PERIOD); break; case SQLITE_ROW: { for(j=0; j<num_cols; j++) { fprintf(fp, str_fmt[j], (char *) sqlite3_column_text(stmt,j)); } printf("\n"); count++; break; } } } sqlite3_finalize(stmt); return count; }
char *config_get_fqdn() { char *sql = NULL, *fqdn = NULL, *tmp = NULL; int result_size = 0, err_code = 0, fqdn_size = 0; sql = sqlite3_mprintf("SELECT value FROM %s WHERE key = %Q LIMIT 1",CONFIG_TABLE,FQDN_NAME); fqdn = sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); fqdn = NULL; } else if(fqdn){ tmp = fqdn; fqdn_size = strlen(fqdn) + 2; fqdn = realloc(fqdn,fqdn_size); if(!fqdn){ perror("Malloc failure"); if(tmp) free(tmp); } else { memset((fqdn+fqdn_size-2),'.',1); memset((fqdn+fqdn_size-1),'\0',1); } } return fqdn; }
void config_set_cookie(char *cookie) { char *sql = NULL; int result_size = 0, err_code = 0; sql = sqlite3_mprintf("INSERT OR REPLACE INTO %s (key,value) VALUES (%Q, %Q)",CONFIG_TABLE,COOKIE_NAME,cookie); sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); } return; }
void config_set_callback_port(char *port) { char *sql = NULL; int result_size = 0, err_code = 0; sql = sqlite3_mprintf("INSERT OR REPLACE INTO %s (key,value,no_reconfig) VALUES (%Q,%Q,1)",CONFIG_TABLE,CALLBACK_PORT_NAME,port); sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); } return; }
void config_set_fqdn(char *fqdn) { char *sql = NULL; int result_size = 0, err_code = 0; sql = sqlite3_mprintf("INSERT OR REPLACE INTO %s (key,value,no_reconfig) VALUES (%Q,%Q,1)",CONFIG_TABLE,FQDN_NAME,fqdn); sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); } return; }
char *config_get_callback_port() { char *sql = NULL, *port = NULL; int result_size = 0, err_code = 0; sql = sqlite3_mprintf("SELECT value FROM %s WHERE key = %Q LIMIT 1",CONFIG_TABLE,CALLBACK_PORT_NAME); port = sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); port = NULL; } return port; }
char *config_get_fqdn_np() { char *sql = NULL, *fqdn = NULL; int result_size = 0, err_code = 0; sql = sqlite3_mprintf("SELECT value FROM %s WHERE key = %Q LIMIT 1",CONFIG_TABLE,FQDN_NAME); fqdn = sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); fqdn = NULL; } return fqdn; }
char *config_get_user() { char *sql = NULL, *user = NULL; int result_size = 0, err_code = 0; sql = sqlite3_mprintf("SELECT value FROM %s WHERE key = %Q LIMIT 1",CONFIG_TABLE,USER_NAME); user = sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); user = NULL; } return user; }
/* Check to see if the requested file type has been marked as filtered in the filter table */ int is_url_filtered(char *url) { char *id = NULL, *query = NULL, *requested_file = NULL, *ext_ptr = NULL; int result_size = 0, err_code = 0; /* Make a copy of the request */ requested_file = strdup(url); if(!requested_file){ perror("Malloc failure"); return 0; } /* Point ext_ptr to the end of the file name */ if((ext_ptr = strstr(requested_file,QUESTION_MARK)) == NULL){ ext_ptr = (requested_file + strlen(requested_file)); } memset(ext_ptr,0,1); /* Work backwards from the end of the file name to the first period. That's the extension. */ while(ext_ptr > requested_file){ if(memcmp(ext_ptr,PERIOD,PERIOD_SIZE) == 0){ break; } ext_ptr--; } /* Build and execute the query */ query = sqlite3_mprintf("SELECT id FROM %s WHERE extension = %Q LIMIT 1",FILTER_TABLE,ext_ptr); id = sql_exec(query,&result_size,&err_code); if(err_code != SQLITE_OK){ sql_log_error(); } /* Free memory */ if(requested_file) free(requested_file); if(id) free(id); sqlite3_free(query); /* Determine result */ if(result_size != 0){ return 1; } return 0; }
void config_set_path(char *path) { char *sql = NULL; int result_size = 0, err_code = 0; if(path[0] == '/'){ sql = sqlite3_mprintf("INSERT OR REPLACE INTO %s (key,value) VALUES (%Q,%Q)",CONFIG_TABLE,PATH_NAME,path); } else { sql = sqlite3_mprintf("INSERT OR REPLACE INTO %s (key,value) VALUES (%Q,'/%q')",CONFIG_TABLE,PATH_NAME,path); } sql_exec(sql,&result_size,&err_code); sqlite3_free(sql); if(err_code != SQLITE_OK){ sql_log_error(); } return; }
/* * Queries the database for the public / private keypair that matches the fingerprint stored in certinfo. * If found, the certificate / key members of the keymaster struct are populated accordingly. * Returns 1 on success, 0 on failure. */ int lookup_key(struct keymaster *certinfo) { int result_size = 0, err_code = 0, retval = 1; char *desc_query = NULL, *priv_query = NULL, *pub_query = NULL; if(sql_init(DB_NAME, DB_LOCAL) != SQLITE_OK) { goto error; } priv_query = sqlite3_mprintf("SELECT key FROM certificates WHERE fingerprint = %Q", certinfo->fingerprint); certinfo->key = sql_exec(priv_query, &result_size, &err_code); sqlite3_free(priv_query); if(err_code != SQLITE_OK) { goto error; } pub_query = sqlite3_mprintf("SELECT certificate FROM certificates WHERE fingerprint = %Q", certinfo->fingerprint); certinfo->certificate = sql_exec(pub_query, &result_size, &err_code); sqlite3_free(pub_query); if(err_code != SQLITE_OK) { goto error; } desc_query = sqlite3_mprintf("SELECT description FROM certificates WHERE fingerprint = %Q", certinfo->fingerprint); certinfo->description = sql_exec(desc_query, &result_size, &err_code); sqlite3_free(desc_query); if(err_code != SQLITE_OK) { goto error; } goto end; error: sql_log_error(); retval = 0; end: sql_cleanup(); return retval; }
/* Dumps search results that match the provided query term */ void print_search_results(char *term) { int count = 0; char *query = NULL, *q = NULL, *table = NULL; /* Format strings for the respective columns retrieved in sql_dump() */ char *col_fmt[NUM_COLS] = {"%-25s", "%-50s", "%-25s", "%-25s", "%-15s", "%-50s"}; if(sql_init(DB_NAME, DB_LOCAL) != SQLITE_OK) { sql_log_error(); goto end; } /* Queries should be in the format: <table.column>=<search term> */ table = strdup(term); q = strstr(table, QUERY_DELIMITER); if(!q) { fprintf(stderr, "ERROR: Improperly formatted query!\n"); goto end; } memset(q, 0, 1); q++; query = sqlite3_mprintf("SELECT firmware.vendor,firmware.description,hardware.vendor,model,revision,hardware.description FROM firmware JOIN hardware ON firmware.device_id=hardware.id WHERE %s LIKE '%%%q%%'", table, q); /* Print out a table of all relevant database info related to this certificate */ printf("\n%s\n%s\n", COL_HEADERS, HEADER_DELIM); count = sql_dump(query, col_fmt, NUM_COLS, stdout); printf("\nFound %d matches for '%s'.\n\n", count, q); end: if(table) free(table); sqlite3_free(query); sql_cleanup(); return; }
/* Prints out all information related to the selected certificate to stdout */ void print_all_cert_info(struct keymaster *certinfo) { int count = 0; char *query = NULL; /* Format strings for the respective columns retrieved in sql_dump() */ char *col_fmt[NUM_COLS] = {"%-25s", "%-50s", "%-25s", "%-25s", "%-15s", "%-50s"}; if(sql_init(DB_NAME, DB_LOCAL) != SQLITE_OK) { sql_log_error(); return; } query = sqlite3_mprintf("SELECT firmware.vendor,firmware.description,hardware.vendor,model,revision,hardware.description FROM firmware JOIN hardware ON firmware.device_id=hardware.id WHERE certificate_id = (SELECT id FROM certificates WHERE fingerprint = %Q)", certinfo->fingerprint); /* Print out a table of all relevant database info related to this certificate */ printf("\n%s\n%s\n", COL_HEADERS, HEADER_DELIM); count = sql_dump(query, col_fmt, NUM_COLS, stdout); printf("\nFound %d firmware(s) using this certificate.\n\n", count); sqlite3_free(query); sql_cleanup(); return; }
/* Used by the proxy server to display active IPs. Prints results to csock. */ void print_client_list(int csock) { int rc = 0, col_type = 0, line_size = 0, class_toggle = TD_GREY; sqlite3_stmt *stmt = NULL; char *ip = NULL, *timestamp = NULL, *line = NULL; char *query = NULL, *path = NULL, *attack_port = NULL; /* Write out the HTML table headers */ if(write(csock,CLIENT_TABLE_HEADERS,CLIENT_TABLE_HEADERS_SIZE) != CLIENT_TABLE_HEADERS_SIZE) { glog("Proxy server failed to write out the client table headers",LOG_ERROR_TYPE); return; } /* Prepare the SQL query */ query = sqlite3_mprintf("SELECT ip,callback_time FROM %s WHERE strftime('%%s',callback_time) > strftime('%%s','now') ORDER BY id",CLIENTS_TABLE); if(!query) { sql_log_error(); return; } rc = sqlite3_prepare_v2(globals.db,query,strlen(query),&stmt,NULL); if(rc != SQLITE_OK) { sql_log_error(); sqlite3_free(query); return; } path = config_get_path(); attack_port = config_get_attack_port(); /* Loop until the query has finished */ while((rc = sqlite3_step(stmt)) != SQLITE_DONE) { switch(rc) { case SQLITE_ERROR: sql_log_error(); sqlite3_finalize(stmt); sqlite3_free(query); if(path) free(path); if(attack_port) free(attack_port); return; case SQLITE_BUSY: /* If the table is locked, wait then try again */ usleep(BUSY_WAIT_PERIOD); break; case SQLITE_ROW: { col_type = sqlite3_column_type(stmt,0); switch(col_type) { case SQLITE_TEXT: ip = (void *) sqlite3_column_text(stmt,0); timestamp = (void *) sqlite3_column_text(stmt,1); line = sqlite3_mprintf("<tr class=\"tr%d\" onmouseover=\"lock_updates()\" onmouseout=\"unlock_updates()\" onclick=\"go('%s:%s%s')\"><td>%s</td><td>%s</td></tr>",class_toggle,ip,attack_port,path,ip,timestamp); if(!line) { glog("Failed to generate Web UI entry",LOG_ERROR_TYPE); break; } line_size = strlen(line); if(write(csock,line,line_size) != line_size) { glog("Proxy server failed to write out active client list to Web UI",LOG_ERROR_TYPE); } /* Toggle the class (and thus, the color) of the next table row */ if(class_toggle) { class_toggle = TD_GREY; } else { class_toggle = TD_WHITE; } sqlite3_free(line); line_size = 0; break; } } } } sqlite3_finalize(stmt); sqlite3_free(query); if(path) free(path); if(attack_port) free(attack_port); return; }
int proxy_server() { int rx_bytes = 0, post_data_size = 0; int lsock = 0, csock = 0, client_data_size = 0; int result_size = 0, err_code = 0, id = 0; int addrlen = sizeof(struct sockaddr_in); struct sockaddr_in clientaddr; char *buffer = NULL, *post_data = NULL; char *host = NULL, *url = NULL; char *query = NULL, *fifo_file = NULL; char *get_data = NULL; char *client_data = NULL, *headers = NULL; char *server_ip = NULL; memset((void *) &clientaddr,0,addrlen); server_ip = config_get_server_ip(); /* Create TCP socket */ if((lsock = create_socket(server_ip,PROXY_PORT,SOCK_STREAM)) == SOCK_FAIL) { glog("Failed to create TCP socket for proxy server",LOG_ERROR_TYPE); if(server_ip) free(server_ip); return EXIT_FAILURE; } if(server_ip) free(server_ip); /* Infinite receive loop */ while(1) { /* Accept incoming connection */ if((csock = accept(lsock,(struct sockaddr *) &clientaddr,(socklen_t *) &addrlen)) < 0) { glog("Failed to accept TCP connection to proxy server",LOG_ERROR_TYPE); if(buffer) free(buffer); return EXIT_FAILURE; } if(!fork()) { /* Receive client request */ if((buffer = receive(lsock,SOCK_STREAM,&rx_bytes,csock,&clientaddr)) == NULL) { glog("Failed to read data from client request sent to proxy server",LOG_ERROR_TYPE); exit(EXIT_FAILURE); } if(is_using_proxy(buffer)) { /* Get the target's IP address */ host = get_host_name(buffer); /* Get the target URL path */ url = get_url(buffer); /* Get POST data, if any */ post_data = get_post_data(buffer,rx_bytes,&post_data_size); /* Get HTTP headers from request */ headers = get_headers(buffer); /* If the CONSOLE_HOST is requested, then display the Web console interface */ if(memcmp(host,CONSOLE_HOST,CONSOLE_HOST_SIZE) == 0) { show_web_ui(csock,url); close_socket(csock); } else { /* Make sure the requested host is in our clients list */ query = sqlite3_mprintf("SELECT id FROM %s WHERE strftime('%%s',callback_time) >= strftime('%%s','now') AND ip = %Q LIMIT 1",CLIENTS_TABLE,host); sql_exec(query,&result_size,&err_code); sqlite3_free(query); if(result_size > 0) { /* Don't allow requests for filtered file extensions */ if(!is_url_filtered(url)) { fifo_file = create_fifo(host); if(!fifo_file) { glog("Failed to create fifo file",LOG_ERROR_TYPE); } else { /* Insert query into queue table */ query = sqlite3_mprintf("INSERT INTO %s (fifo,host,url,headers,pdata,sent) VALUES (%Q,%Q,%Q,%Q,%Q,0)",QUEUE_TABLE,fifo_file,host,url,headers,post_data); sql_exec(query,&result_size,&err_code); sqlite3_free(query); if(err_code != SQLITE_OK) { sql_log_error(); } else { /* When the client data has returned, the callback server will write the ID of the callback to the FIFO */ id = read_from_fifo(fifo_file); /* Extract the data from the DB */ get_data = sqlite3_mprintf("SELECT rdata FROM %s WHERE id = '%d'",QUEUE_TABLE,id); client_data = sql_exec(get_data,&client_data_size,&err_code); sqlite3_free(get_data); if(err_code != SQLITE_OK) { sql_log_error(); } else { /* Write data to socket */ if(write(csock,client_data,client_data_size) != client_data_size) { glog("Proxy socket write failed",LOG_ERROR_TYPE); } } if(client_data) free(client_data); /* Make sure the fifo gets deleted */ destroy_fifo(fifo_file); } } } } } } /* Exit the child process */ close_socket(csock); if(fifo_file) free(fifo_file); if(buffer) free(buffer); if(host) free(host); if(url) free(url); if(post_data) free(post_data); if(headers) free(headers); exit(EXIT_SUCCESS); } } /* Close up shop */ close_socket(csock); close_socket(lsock); return EXIT_FAILURE; }