Quote:
Originally Posted by nadroj
i imagine you have to link with the appropriate libraries when you compile it? check the documentation of the libraries for info on that.
let us know what you typed to compile it. also, if you want help to fix those warning messages, post your code. the warnings arent deadly, but should and can be avoided.
|
This is the code which i compiled to do the concept called portknocking at Server side.....
// knockd.c - port knocking daemon
// Copyright (C) 2004 Matt Doyle <jmdoyle@cmu.edu>
//
// 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.
// #INCLUDES
#include <slack/std.h> // from libslack (libslack.org), used for daemonizing
#include <slack/daemon.h> // from libslack (libslack.org), used for daemonizing
#include <stdio.h>
#include <stdlib.h>
#include <regex.h> // regular expression support
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include <md5.h> // md5 support
#include <openssl/blowfish.h> // blowfish support
#include <time.h>
#include <signal.h>
#include "knock.h"
// #DEFINES
#define NUMOFSUBEXPS 3 // number of subexpressions in our regular expression
// GLOBALS
struct hostdata *hosts; // linked list of host nodes
// FUNCTION PROTOTYPES
void init_hostdata(struct hostdata *host);
void eval_sequence(struct hostdata *host, BF_KEY bfkey, unsigned short int offset);
void free_node(struct hostdata *host);
struct hostdata *add_host_to_list(struct hostdata *host);
struct hostdata *host_exists(char *remotehost);
void check_timestamps(time_t window);
void modify_ipfilter_firewall(struct hostdata *host);
void end_program(void);
// START MAIN
int main(int argc, char *argv[]){
// VARIABLES
unsigned int sleeptime = 1; // # of seconds to wait between md5 hash checks
char md5hash[33]; // stores md5 hash
char logfile[50]; // log file name
char logline[200]; // stores lines from log file as we pull them out
char remotehost[16]; // stores subexpression from regexp match
char localport[6]; // stores subexpression from regexp match
char offsetstring[6]; // stores offset in string form
char password[MAXPASSWDSIZE]; // encryption/decryption password
regex_t regexp; // stores compiled regular expression
regmatch_t subexps[NUMOFSUBEXPS]; // stores matched subexpressions of our regexp
fpos_t position; // stores file pointer
FILE *logfileptr;
BF_KEY bfkey;
struct hostdata *currenthost; // pointer to current host node being dealt with
time_t window = 10; // amount of time to receive all knocks from a host before freeing the node // FIX!
unsigned short int offset = 0; // port range offset
// CLEAR BUFFERS
memset(md5hash, '\0', sizeof(md5hash));
memset(logfile, '\0', sizeof(logfile));
memset(logline, '\0', sizeof(logline));
memset(remotehost, '\0', sizeof(remotehost));
memset(localport, '\0', sizeof(localport));
memset(offsetstring, '\0', sizeof(offsetstring));
memset(password, '\0', sizeof(password));
// INITIALIZE
memcpy(logfile, "/var/log/messages", sizeof(logfile)-1);
logfileptr = NULL;
hosts = NULL;
// PROMPT FOR ENCRYPTION PASSWORD
strcpy(password, getpass("Enter decryption password: "));
BF_set_key(&bfkey, sizeof(password), password);
// PROMPT FOR PORT OFFSET
printf("Enter port offset: ");
fgets(offsetstring, 5, stdin);
if((offset = (unsigned short int) strtol(offsetstring, NULL, 10)) > 65279){
printf("ERROR: Port offset > 65279\n");
exit(0);
}
// DAEMONIZE
daemon_init(argv[0]);
signal(SIGINT, end_program);
signal(SIGTERM, end_program);
// GET INITIAL MD5 HASH OF LOGFILE
if(MD5File(logfile, md5hash) == NULL){
printf("ERROR: Log file %s not found.\n", logfile);
end_program();
}
// OPEN LOG FILE FOR READING
if((logfileptr = fopen(logfile, "r")) == NULL){
perror("ERROR");
end_program();
}
// COMPILE REGULAR EXPRESSION
if(regcomp(®exp, "^.+Connection attempt to TCP [0-9.]+
[0-9]+) from [0-9.]+):[0-9]+", REG_EXTENDED) != 0)
{
printf("ERROR: Unable to compile regular expression.\n");
exit(0);
}
// SAVE FILE POINTER FROM INITIAL EOF
fseek(logfileptr, 0, SEEK_END);
fgetpos(logfileptr, &position);
rewind(logfileptr);
// START MAIN WHILE LOOP
//printf("Running...\n\n");
while(1){ // FIX!
// IF LOG FILE UNCHANGED, SLEEP THEN LOOP AGAIN
if(strcmp(MD5File(logfile, NULL), md5hash) == 0){
check_timestamps(window);
sleep(sleeptime);
continue;
}
fsetpos(logfileptr, &position);
// LOOP OVER ALL LOG FILE LINES FROM SAVED POINT ON
while(!feof(logfileptr)){
check_timestamps(window);
memset(logline, '\0', sizeof(logline));
fgets(logline, sizeof(logline), logfileptr);
if(regexec(®exp, logline, NUMOFSUBEXPS, subexps, 0) == 0){
memcpy(localport, logline+subexps[1].rm_so, (subexps[1].rm_eo-subexps[1].rm_so));
memcpy(remotehost, logline+subexps[2].rm_so, (subexps[2].rm_eo-subexps[2].rm_so));
//printf("%s knocking port %s\n", remotehost, localport);
// ADD HOST ENTRY IF IT DOESN'T EXIST, UPDATE IF IT DOES
if((currenthost = host_exists(remotehost)) == NULL){
currenthost = malloc(sizeof(struct hostdata));
init_hostdata(currenthost);
hosts = add_host_to_list(currenthost);
strcpy(currenthost->originIP, remotehost);
currenthost->knocks_enc[currenthost->knocksreceived] = (unsigned short int) strtol(localport, NULL, 10);
currenthost->knocksreceived++;
}
else{
currenthost->knocks_enc[currenthost->knocksreceived] = (unsigned short int) strtol(localport, NULL, 10);
currenthost->knocksreceived++;
if(currenthost->knocksreceived == MAXNUMOFKNOCKS)
eval_sequence(currenthost, bfkey, offset);
}
memset(localport, '\0', sizeof(localport));
memset(remotehost, '\0', sizeof(remotehost));
memset(subexps, '\0', sizeof(subexps));
} // END IF
else continue;
} // END WHILE
// SAVE NEW LOG FILE HASH AND NEW EOF POINTER
MD5File(logfile, md5hash);
fseek(logfileptr, 0, SEEK_END);
fgetpos(logfileptr, &position);
} // END WHILE
// CLEAN UP
fclose(logfileptr);
end_program();
return 0; // should never get here
} // END MAIN
/* ********** FUNCTION DEFINITIONS ********** */
// INIT_HOSTDATA
// Initializes fields of hostdata structures.
void init_hostdata(struct hostdata *host){
memset(host->originIP, '\0', sizeof(host->originIP));
memset(host->blf_in, '0', sizeof(host->blf_in));
memset(host->blf_out, '\0', sizeof(host->blf_out));
memset(host->knocks_enc, 0, sizeof(host->knocks_enc));
memset(host->knocks_dec, 0, sizeof(host->knocks_dec));
host->knocksreceived = 0;
host->next = NULL;
host->timestamp = time(NULL);
}
// ADD_HOST_TO_LIST
// Adds new host structures to linked list.
struct hostdata *add_host_to_list(struct hostdata *host){
// VARIABLES
struct hostdata *current;
current = hosts;
if(current == NULL)
return host;
while(current->next != NULL){
current = current->next;
}
current->next = host;
return hosts;
}
// HOST_EXISTS
// Tests to see if a node exists for a given host.
struct hostdata *host_exists(char *remotehost){
// VARIABLES
struct hostdata *current;
current = hosts;
while(current != NULL){
if(strcmp(current->originIP, remotehost) == 0)
return current;
current = current->next;
}
return NULL;
}
// EVAL_SEQUENCE
// Extracts knock information from a given host node and modifies the firewall
// accordingly.
void eval_sequence(struct hostdata *host, BF_KEY bfkey, unsigned short int offset){
// VARIABLES
unsigned short int upper = 0;
unsigned short int lower = 0;
//printf("\nKnock sequence: %d %d %d %d %d %d %d %d\n", host->knocks_enc[0], host->knocks_enc[1], host->knocks_enc[2], host->knocks_enc[3], host->knocks_enc[4], host->knocks_enc[5], host->knocks_enc[6], host->knocks_enc[7]);
host->blf_in[0] = ((unsigned char) host->knocks_enc[0]) - offset;
host->blf_in[1] = ((unsigned char) host->knocks_enc[1]) - offset;
host->blf_in[2] = ((unsigned char) host->knocks_enc[2]) - offset;
host->blf_in[3] = ((unsigned char) host->knocks_enc[3]) - offset;
host->blf_in[4] = ((unsigned char) host->knocks_enc[4]) - offset;
host->blf_in[5] = ((unsigned char) host->knocks_enc[5]) - offset;
host->blf_in[6] = ((unsigned char) host->knocks_enc[6]) - offset;
host->blf_in[7] = ((unsigned char) host->knocks_enc[7]) - offset;
BF_ecb_encrypt(host->blf_in, host->blf_out, &bfkey, BF_DECRYPT);
host->knocks_dec[0] = (unsigned short int) host->blf_out[0];
host->knocks_dec[1] = (unsigned short int) host->blf_out[1];
host->knocks_dec[2] = (unsigned short int) host->blf_out[2];
host->knocks_dec[3] = (unsigned short int) host->blf_out[3];
upper = host->blf_out[4] << 8;
lower = (unsigned short int) host->blf_out[5];
host->knocks_dec[4] = upper | lower;
host->knocks_dec[6] = (unsigned short int) host->blf_out[6];
//printf("Decrypted IP: %u.%u.%u.%u\n", host->knocks_dec[0], host->knocks_dec[1], host->knocks_dec[2], host->knocks_dec[3]);
//printf("Action: ");
//if(host->knocks_dec[6] == 1) printf("Open ");
//else if(host->knocks_dec[6] == 0) printf("Close ");
//else printf("NO ACTION ");
//printf("port %d to IP address %d.%d.%d.%d\n\n", host->knocks_dec[4], host->knocks_dec[0], host->knocks_dec[1], host->knocks_dec[2], host->knocks_dec[3]);
modify_ipfilter_firewall(host);
free_node(host);
}
// FREE_NODE
// Removes a processed node from the linked list.
void free_node(struct hostdata *host){
// VARIABLES
struct hostdata *previous;
struct hostdata *current;
if(host == hosts){ // if the node to free is the first in the list
current = host;
hosts = host->next;
free(current);
}
else{
previous = hosts;
current = hosts->next;
while(current != host){
previous = current;
current = current->next;
}
if(current->next != NULL)
previous->next = current->next;
else
previous->next = NULL;
free(current);
}
}
// CHECK_TIMESTAMPS
// Removes expired nodes from the linked list.
void check_timestamps(time_t window){
// VARIABLES
struct hostdata *current;
current = hosts;
while(current != NULL){
if(difftime(time(NULL), current->timestamp) >= window)
free_node(current);
current = current->next;
}
}
// MODIFY_IPFILTER_FIREWALL
// Subroutine for modifying an ipfilter firewall.
void modify_ipfilter_firewall(struct hostdata *host){
// VARIABLES
int ruleexists = 0;
int ruledeleted = 0;
char firewallrule[74]; // stores string of our firewall rule
char filebuffer[74]; // stores lines as they are read out of rule file
char buffer[6]; // storage buffer
regex_t regexp;
FILE *rulefile;
FILE *tempfile;
// INITIALIZE BUFFERS
memset(firewallrule, '\0', sizeof(firewallrule));
memset(buffer, '\0', sizeof(buffer));
// COMPOSE FIREWALL RULE STRING
strncat(firewallrule, " pass in quick on sis0 proto tcp from ", 38);
sprintf(buffer, "%d.%d.%d.%d", host->knocks_dec[0], host->knocks_dec[1], host->knocks_dec[2], host->knocks_dec[3]);
strncat(firewallrule, buffer, 15);
strncat(firewallrule, " to any port = ", 15);
memset(buffer, '\0', sizeof(buffer));
sprintf(buffer, "%d\n", host->knocks_dec[4]);
strncat(firewallrule, buffer, 15);
// COMPILE REGULAR EXPRESSION
if(regcomp(®exp, firewallrule, REG_EXTENDED) != 0){
printf("ERROR: Unable to compile regular expression.\n");
exit(0);
}
// OPEN KNOCKD FIREWALL RULES FILE
if((rulefile = fopen("/etc/ipf.rules.knockd", "a+")) == NULL){
printf("ERROR: Unable to open ipf.rules.knockd\n");
exit(0);
}
// OPEN TEMPORARY FILE
if((tempfile = fopen("/tmp/temp", "w")) == NULL){
printf("ERROR: Unable to open temporary file.\n");
exit(0);
}
// IMMEDIATELY INSERT RULE IF FILE EMPTY AND ACTION IS TO OPEN
if(feof(rulefile) && host->knocks_dec[6] == 1)
fprintf(rulefile, firewallrule);
// DO NOTHING IF FILE IS EMPTY AND ACTION IS TO CLOSE
else if(feof(rulefile) && host->knocks_dec[6] == 0)
{} // do nothing
// LOOP THROUGH OUR RULE FILE
else{
while(!feof(rulefile)){
fgets(filebuffer, 74, rulefile);
filebuffer[73] = '\0';
// IF RULE MATCHES AND ACTION IS TO OPEN...
if((regexec(®exp, filebuffer, 0, NULL, 0) == 0) && (host->knocks_dec[6] == 1)){
ruleexists = 1;
break;
}
// IF RULE DOESN'T MATCH AND ACTION IS TO OPEN...
else if((regexec(®exp, filebuffer, 0, NULL, 0) != 0) && (host->knocks_dec[6] == 1))
continue;
// IF RULE MATCHES AND ACTION IS TO CLOSE...
else if((regexec(®exp, filebuffer, 0, NULL, 0) == 0) && (host->knocks_dec[6] == 0)){
ruledeleted = 1;
continue;
}
// IF RULE DOESN'T MATCH AND ACTION IS TO CLOSE...
else if((regexec(®exp, filebuffer, 0, NULL, 0) != 0) && (host->knocks_dec[6] == 0)){
fprintf(tempfile, filebuffer);
continue;
}
} // END WHILE
// APPEND RULE TO OPEN IF IT DOESN'T EXIST
if((ruleexists == 0) && (host->knocks_dec[6] == 1)){
fprintf(rulefile, firewallrule);
fclose(rulefile);
system("ipf -Fa -f /etc/ipf.rules.knockd -f /etc/ipf.rules");
fclose(tempfile);
}
// DELETE RULE IF IT EXISTS AND ACTION IS TO CLOSE
else if((ruledeleted == 1) && (host->knocks_dec[6] == 0)){
fclose(rulefile);
if(unlink("/etc/ipf.rules.knockd")){
printf("ERROR: Unable to delete rule file.\n");
exit(0);
}
fclose(tempfile);
if(rename("/tmp/temp", "/etc/ipf.rules.knockd")){
printf("ERROR: Unable to rename file.\n");
exit(0);
}
system("ipf -Fa -f /etc/ipf.rules.knockd -f /etc/ipf.rules");
}
// DELETE TEMP FILE
if(unlink("/tmp/temp")){
printf("ERROR: Unable to delete temp file.\n");
exit(0);
}
} // END ELSE
}
// END_PROGRAM
// Subroutine for cleaning up and shutting down.
void end_program(void){
daemon_close();
system("ipf -Fa -f /etc/ipf.rules"); // ipfilter dependent, fix this in future
unlink("/etc/ipf.rules.knockd");
exit(0);
}