Author: marten Date: Wed Aug 19 11:54:30 2009 New Revision: 824 Log: Added management-tool to pairing changed pairing to use libpisa for hitlist, etc. Added: trunk/pairing/management.c (contents, props changed) trunk/pairing/management.h Modified: trunk/libpisa/config.c trunk/pairing/Makefile.am trunk/pairing/accept.c trunk/pairing/accept.h trunk/pairing/common.c trunk/pairing/common.h trunk/pairing/common_headers.c trunk/pairing/common_headers.h trunk/pairing/libconfig_wrapper.c trunk/pairing/libconfig_wrapper.h trunk/pairing/packet_handler_accept.c trunk/pairing/packet_handler_accept.h Modified: trunk/libpisa/config.c ============================================================================== --- trunk/libpisa/config.c Tue Aug 18 15:21:27 2009 (r823) +++ trunk/libpisa/config.c Wed Aug 19 11:54:30 2009 (r824) @@ -25,11 +25,11 @@ /** * Setup the config module for work. Call this before any other * call to the config module happens, and call it only once until a - * matching call to configCleanup was made. + * matching call to pisa_cfg_cleanup was made. * @param file Opened file from which the configuration shall be red * @return 1 -> Success * @return 0 -> Failure - * @sa configCleanup + * @sa pisa_cfg_cleanup */ int pisa_cfg_setup(FILE* file) { @@ -50,13 +50,13 @@ /** * Setup the config module for work. Call this before any other * call to the config module happens, and call it only once until a - * matching call to configCleanup was made. + * matching call to pisa_cfg_cleanup was made. * * @param file full path to the config file which should be used * @return 1 -> Success * @return 0 -> Failure * @sa configSetup - * @sa configCleanup + * @sa pisa_cfg_cleanup */ int pisa_cfg_setup_file(const char* file) { @@ -265,9 +265,9 @@ /** * Cleanup config library. This call must always match calls to - * configAuthorizedHostsSetup or configAuthorizedHostsSetupFile - * @sa configAuthorizedHostsSetup - * @sa configAuthorizedHostsSetupFile + * pisa_cfg_authorized_hosts_setup or pisa_cfg_authorized_hosts_setup_file + * @sa pisa_cfg_authorized_hosts_setup + * @sa pisa_cfg_authorized_hosts_setup_file */ void pisa_cfg_authorized_hosts_cleanup(void) { @@ -277,13 +277,13 @@ /** * Setup the authorized hosts config module for work. Call this before any other * call to the authorized hosts config module happens, and call it only once until a - * matching call to configAuthorizedHostsCleanup was made. + * matching call to pisa_cfg_authorized_hosts_cleanup was made. * * @param file full path to the config file which should be used * @return 1 -> Success * @return 0 -> Failure - * @sa configAuthorizedHostsSetup - * @sa configAuthorizedHostsCleanup + * @sa pisa_cfg_authorized_hosts_setup + * @sa pisa_cfg_authorized_hosts_cleanup */ int pisa_cfg_authorized_hosts_setup_file(const char* file) { @@ -306,11 +306,11 @@ /** * Setup the authorized hosts config module for work. Call this before any other * call to the authorized hosts config module happens, and call it only once until a - * matching call to configAuthorizedHostsCleanup was made. + * matching call to pisa_cfg_authorized_hosts_cleanup was made. * @param file Opened file from which the configuration shall be red * @return 1 -> Success * @return 0 -> Failure - * @sa configAuthorizedHostsCleanup + * @sa pisa_cfg_authorized_hosts_cleanup */ int pisa_cfg_authorized_hosts_setup(FILE* file) { @@ -330,12 +330,12 @@ /** * Save the changes made to the authorized hosts config. The authorized hosts - * config has to be set up with configAuthorizedHostsSetup or - * configAuthorizedHostsSetupFile + * config has to be set up with pisa_cfg_authorized_hosts_setup or + * pisa_cfg_authorized_hosts_setup_file * @return 1 -> Success * @return 0 -> Failure - * @sa configAuthorizedHostsSetup - * @sa configAuthorizedHostsCleanup + * @sa pisa_cfg_authorized_hosts_setup + * @sa pisa_cfg_authorized_hosts_cleanup */ int pisa_cfg_write_authorized_hosts_file(void) { Modified: trunk/pairing/Makefile.am ============================================================================== --- trunk/pairing/Makefile.am Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/Makefile.am Wed Aug 19 11:54:30 2009 (r824) @@ -11,15 +11,16 @@ CFLAGS = -Wall -g -I$(top_srcdir)/libpisa/libconfig-1.3.2 # add -pedantic if you want it to worry about your commenting style (and other stuff) send_CFLAGS = -DSEND accept_CFLAGS = -DACCEPT -bin_PROGRAMS = send accept passgen +bin_PROGRAMS = send accept passgen management senddir = . acceptdir = . passgendir = . +managementdir = . include_HEADERS = common_headers.h send.h common.h packet_handler.h hash.h libconfig_wrapper.h packet_handler_send.h create_send_headers.h include_HEADERS += hash.h accept.h common_headers.h packet_handler.h libconfig_wrapper.h common.h packet_handler_accept.h create_accept_headers.h -include_HEADERS += hash.h +include_HEADERS += hash.h management.h EXTRA_DIST = readme.txt \ defaults/authorized_hosts.cfg defaults/known_relays.cfg defaults/relay_config.cfg \ @@ -34,9 +35,9 @@ LDFLAGS += -L$(top_srcdir)/libpisa/libconfig-1.3.2 else if PISA_FORCE_SHLIBCONFIG - LDADD += -lconfig + LDADD += @PISA_LIBPISA_LIB_STATIC@ -lconfig else - LDADD += @PISA_LIBCONFIG_LIB_STATIC@ + LDADD += @PISA_LIBPISA_LIB_STATIC@ @PISA_LIBCONFIG_LIB_STATIC@ endif endif @@ -47,3 +48,4 @@ send_SOURCES = send.c common_headers.c common.c packet_handler.c hash.c libconfig_wrapper.c packet_handler_send.c create_send_headers.c accept_SOURCES = accept.c hash.c common_headers.c packet_handler.c libconfig_wrapper.c common.c packet_handler_accept.c create_accept_headers.c passgen_SOURCES = passgen.c hash.c +management_SOURCES = management.c common.c common_headers.c libconfig_wrapper.c Modified: trunk/pairing/accept.c ============================================================================== --- trunk/pairing/accept.c Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/accept.c Wed Aug 19 11:54:30 2009 (r824) @@ -7,114 +7,186 @@ * @file accept.c * @brief Main program of the pairing application. * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ +#include "global.h" /* it must be included before all other header files */ +#include "config.h" +#include "hitlist.h" #include "accept.h" +extern config_t authorized_cfg; + struct global_accept_variables global_accept = {0}; -/** Main program that will be run on the relay. +/** Main program that will be run on the relay. */ int main(int argc, char *argv[]) { - struct sockaddr_in6 peer_addr; - unsigned int addrlen; - header_general *gen_hdr = malloc(sizeof(header_general)); - int chars_received; // Number of characters received on the socket - char address_string[INET6_ADDRSTRLEN]; // Human-readable address of sender - int msg_type, return_value; - - if (!open_socket_accept()) - { - DEBUG("Socket could not be created. Leaving program.\n"); - return 1; - } - - addrlen = sizeof(struct sockaddr_in6); - - while (1) - { - DEBUG_MED(LINE_BREAK LINE_BREAK); - - // Receive message - DEBUG_MED("Waiting for incoming message..."); - chars_received = recvfrom(global_accept.socket_desc, gen_hdr, sizeof(header_general), 0, (struct sockaddr *)&peer_addr, &addrlen); - DEBUG_MED("Bytes received: %d", chars_received); - - if (chars_received > 0) - { - - - // Get peer address, determine if it's a HIT - inet_ntop(AF_INET6, &peer_addr.sin6_addr, address_string, sizeof(address_string)); - DEBUG("Address of sender is %s", address_string); - if (!ipv6_addr_is_hit(&peer_addr.sin6_addr)) - DEBUG_HIGH("Address is IPv6."); - else - { - DEBUG_HIGH("Address is a HIT!"); - - // Handle the packet (and react accordingly) - handle_packet(&peer_addr, gen_hdr, &msg_type, &return_value); - - print_msg_info(msg_type, return_value); - } - - DEBUG_MED(LINE_BREAK LINE_BREAK); - } - else - perror("receive"); + struct sockaddr_in6 peer_addr; + unsigned int addrlen; + header_general *gen_hdr = malloc(sizeof(header_general)); + int chars_received; // Number of characters received on the socket + char address_string[INET6_ADDRSTRLEN]; // Human-readable address of sender + int msg_type, return_value; + + if (!open_socket_accept()) + { + DEBUG("Socket could not be created. Leaving program.\n"); + return 1; + } + + pisa_cfg_authorized_hosts_setup_file("authorized_hosts.cfg"); + + addrlen = sizeof(struct sockaddr_in6); + + if (signal(SIGALRM, check_expiration_dates) == SIG_ERR) + { + DEBUG("Cannot register signal handler"); + } + check_expiration_dates(SIGALRM); + + + while (1) + { + DEBUG_MED(LINE_BREAK LINE_BREAK); + + // Receive message + DEBUG_MED("Waiting for incoming message..."); + chars_received = recvfrom(global_accept.socket_desc, gen_hdr, sizeof(header_general), 0, (struct sockaddr *)&peer_addr, &addrlen); + DEBUG_MED("Bytes received: %d", chars_received); + + if (chars_received > 0) + { + - } + // Get peer address, determine if it's a HIT + inet_ntop(AF_INET6, &peer_addr.sin6_addr, address_string, sizeof(address_string)); + DEBUG("Address of sender is %s", address_string); + if (!ipv6_addr_is_hit(&peer_addr.sin6_addr)) + DEBUG_HIGH("Address is IPv6."); + else + { + DEBUG_HIGH("Address is a HIT!"); - free(gen_hdr); + // Handle the packet (and react accordingly) + handle_packet(&peer_addr, gen_hdr, &msg_type, &return_value); - // Close the socket - close(global_accept.socket_desc); + print_msg_info(msg_type, return_value); + } - return 0; + DEBUG_MED(LINE_BREAK LINE_BREAK); + } + else + perror("receive"); + + } + + free(gen_hdr); + + pisa_cfg_authorized_hosts_cleanup(); + + // Close the socket + close(global_accept.socket_desc); + + return 0; } int open_socket_accept(void) { - int optval=1; - struct sockaddr_in6 address; + int optval=1; + struct sockaddr_in6 address; - // Create socket - if ((global_accept.socket_desc=socket(PF_INET6, SOCK_DGRAM, 0))==0) - { - perror("Create socket"); - return 0; - } - else - DEBUG_MED("Socket created"); - - if (setsockopt(global_accept.socket_desc, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) - DEBUG_MED("Error with setsockopt\n"); - else - DEBUG_MED("Reusing address."); - - - // Create an IPv6 socket on which to listen - address.sin6_family = AF_INET6; - address.sin6_addr = in6addr_any; - address.sin6_port = htons(PORT); - DEBUG_MED("Parameters set."); - - - // Bind the socket to the port - if (bind(global_accept.socket_desc,(struct sockaddr *)&address,sizeof(address))<0) - { - perror("bind"); - return 0; - } - else - DEBUG_MED("Bound to port %d", PORT); + // Create socket + if ((global_accept.socket_desc=socket(PF_INET6, SOCK_DGRAM, 0))==0) + { + perror("Create socket"); + return 0; + } + else + DEBUG_MED("Socket created"); + + if (setsockopt(global_accept.socket_desc, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) + DEBUG_MED("Error with setsockopt\n"); + else + DEBUG_MED("Reusing address."); + + + // Create an IPv6 socket on which to listen + address.sin6_family = AF_INET6; + address.sin6_addr = in6addr_any; + address.sin6_port = htons(PORT); + DEBUG_MED("Parameters set."); + + + // Bind the socket to the port + if (bind(global_accept.socket_desc,(struct sockaddr *)&address,sizeof(address))<0) + { + perror("bind"); + return 0; + } + else + DEBUG_MED("Bound to port %d", PORT); - return 1; + return 1; } +void check_expiration_dates(int signr) +{ + + pisa_hitlist *hitlist_allowed_hosts; + pisa_hitlist_entry *entry; + int i,changes; + time_t now; + struct tm *ts; + char buffer [80]; + char *name; + + changes = 0; + DEBUG("Checking expiration dates..."); + + hitlist_allowed_hosts = pisa_hitlist_build("allowed_hosts"); + + time(&now); + + + for(i=0;i< hitlist_allowed_hosts->cur_slots;i++) + { + entry = &hitlist_allowed_hosts->entries[i]; + if(difftime(now,entry->expiration)>0) + { + // Convert expiration date to readable format + ts = localtime(&entry->expiration); + strftime(buffer, sizeof(buffer), EXPIRATION_DATE_FORMAT, ts); + + // Get HIT + config_setting_t *g=entry->group; + config_setting_t *parent= config_setting_parent(g); + name = (char *)config_setting_get_string(config_setting_get_member(g, "hit")); + + DEBUG("HIT: %s",name); + DEBUG("With expiration date: %s expired.",buffer); + DEBUG("Removing HIT."); + + if(config_setting_remove_elem(parent,config_setting_index(g)) != CONFIG_TRUE) + { + DEBUG("Error removing HIT"); + } + changes = 1; + } + } + + // Save changes + if (changes) + { + DEBUG("Saving changes to authorized hosts file."); + pisa_cfg_write_authorized_hosts_file(); + } + + pisa_hitlist_destroy(hitlist_allowed_hosts); + alarm(TIMER_INTERVAL); +} Modified: trunk/pairing/accept.h ============================================================================== --- trunk/pairing/accept.h Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/accept.h Wed Aug 19 11:54:30 2009 (r824) @@ -7,6 +7,7 @@ * @file accept.h * @brief Header file of the main program of the pairing application. * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ @@ -19,6 +20,7 @@ #include <sys/socket.h> #include <netinet/in.h> #include <string.h> +#include <signal.h> #include <openssl/sha.h> #include <openssl/rand.h> #include "hash.h" @@ -40,7 +42,9 @@ /** Default port is set statically **/ #define PORT 7000 +#define TIMER_INTERVAL 60 + // Function prototypes int open_socket_accept(); - +void check_expiration_dates(int signr); #endif /* PISA_PAIR_ACCEPT_H */ Modified: trunk/pairing/common.c ============================================================================== --- trunk/pairing/common.c Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/common.c Wed Aug 19 11:54:30 2009 (r824) @@ -7,10 +7,21 @@ * @file common.c * @brief Common modules used for the pairing application. * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ + +#include "global.h" /* it must be included before all other header files */ + +#define __USE_XOPEN +#include <time.h> + #include "common.h" +#include "config.h" +#include "libconfig_wrapper.h" +#include "common_headers.h" + /** Checks to see if addr has only the characters allowed in an IPv6 address (or HIT). * @@ -20,8 +31,8 @@ */ int valid_addr(char *addr) { - assert(addr != NULL); - return !(strspn(addr, "0123456789abcdefABCDEF:") < strlen(addr)); + assert(addr != NULL); + return !(strspn(addr, "0123456789abcdefABCDEF:") < strlen(addr)); } @@ -156,3 +167,159 @@ } +/** + * Reads default expiration from FILE_SERVER_CONFIG + * + * @param buffer Buffer for the expiration string + * + * @return 0 -> Failure + * @return 1 -> Success + */ +int get_default_expiration(char *buffer) +{ + return get_default_expiration_from_config(buffer,FILE_SERVER_CONFIG); +} + +/** + * Reads default expiration from filename + * + * @param buffer Buffer for the expiration string + * @param filename The path to the relay_config file + * + * @return 0 -> Failure + * @return 1 -> Success + */ +int get_default_expiration_from_config(char *buffer,const char *filename) +{ + long int default_expiration_int; + int temp; + + time_t expiration; + + // Obtain the default expiration for a master-password-based connection (in minutes) + temp = get_config_setting((char *)filename, "connection_settings.default_connection_expiration", + CONFIG_TYPE_INT, &default_expiration_int, 0); + if (temp == 0) // Something failed in reading, debug printed by get_config_setting + { + DEBUG("User not remembered."); + return 0; + } + if (default_expiration_int == 0) + { + DEBUG("Could not read setting \'connection_settings.default_connection_expiration\' in file %s", filename); + DEBUG("User not remembered."); + return 0; + } + + default_expiration_int *= 60; // Convert to seconds + + time(&expiration); + expiration += default_expiration_int; // Add default expiration to current time + + + if(convert_time_t_to_formatted_string(&expiration,buffer)!=0) + { + return 1; + }else { + return 0; + } +} + + +/** + * Converts time_t time to EXPIRATION_DATE_FORMAT. + * @param time Pointer to the time_t time + * @param buffer Pointer to the buffer holding the formatted string + * + * @return 1 -> Success + * @return 0 -> Failure + */ +int convert_time_t_to_formatted_string(time_t *time,char *buffer) +{ + struct tm *ts; + size_t temp; + // Convert to format: dd-mm-yyyy hh:mm:ss + ts = localtime(time); + temp = strftime(buffer, LENGTH_TIMEOUT, EXPIRATION_DATE_FORMAT, ts); + return temp!=0; + +} + +int valid_date_string(const char *expiration_date,struct tm *tm_expiration) +{ + DEBUG_HIGH("Parsing date."); + char *c; + // Date format: dd-mm-yyyy hh:mm:ss (24 hour clock) + c = strptime(expiration_date, EXPIRATION_DATE_FORMAT, tm_expiration); + if ((c == NULL) || (*c != 0)) // If c does not point to the terminating character of the string + { // then strptime did not make it all of the way through the string. + DEBUG("Could not parse time-and-date string."); + return 0; + }else + { + return 1; + } + +} + + +/** + * Compares two time strings with the date format EXPIRATION_DATE_FORMAT + * and returns the difference in seconds. + * + * @param time1 The first time string + * @param time2 The second time string + * + * @return time2 - time1 + */ +int compare_time_strings(const char *time1,const char *time2) +{ + struct tm tm_time1,tm_time2; + char *c; + + // Date format: yyyy-mm-dd hh:mm:ss (24 hour clock) + c = strptime(time1, EXPIRATION_DATE_FORMAT, &tm_time1); + if ((c == NULL) || (*c != 0)) // If c does not point to the terminating character of the string + { // then strptime did not make it all of the way through the string. + DEBUG("Could not parse time-and-date string."); + return 0; + } + + // Date format: dd-mm-yyyy hh:mm:ss (24 hour clock) + c = strptime(time2, EXPIRATION_DATE_FORMAT, &tm_time2); + if ((c == NULL) || (*c != 0)) // If c does not point to the terminating character of the string + { // then strptime did not make it all of the way through the string. + DEBUG("Could not parse time-and-date string."); + return 0; + } + + return difftime(mktime(&tm_time1),mktime(&tm_time2)); + +} + +/** Converts a date in human-readable format to its time in seconds. + * + * @param expiration_date Pointer to the string containing the human-readable version. + * @param expiration_seconds Pointer to the long int where the result should be stored. + * + * @return 1 if successful; 0 if failed + */ +int get_expiration_time(char *expiration_date, long int *expiration_seconds) +{ + assert(expiration_date != NULL); + assert(expiration_seconds != NULL); + + struct tm time_offset; + + if(!valid_date_string(expiration_date,&time_offset)) + { + return 0; + } + + DEBUG_HIGH("You specified: %s", asctime(&time_offset)); + + *expiration_seconds = (long int)mktime(&time_offset); + DEBUG_HIGH("Time in seconds: %ld", *expiration_seconds); + + return 1; +} Modified: trunk/pairing/common.h ============================================================================== --- trunk/pairing/common.h Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/common.h Wed Aug 19 11:54:30 2009 (r824) @@ -7,6 +7,7 @@ * @file common.h * @brief Header file of common modules used for the pairing application. * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ @@ -19,6 +20,7 @@ #include <arpa/inet.h> #include <stdio.h> #include <sys/types.h> +#include <time.h> // For function ipv6_addr_is_hit typedef uint32_t hip_closest_prefix_type_t; @@ -33,6 +35,12 @@ int identical_hits(char *hit1, char *hit2); int ipv6_addr_is_hit(const struct in6_addr *hit); void itoa(int n, char s[]); +int get_default_expiration(char *buffer); +int get_default_expiration_from_config(char *buffer,const char *filename); +int valid_date_string(const char *expiration_date,struct tm *tm_expiration); +int compare_time_strings(const char *time1,const char *time2); +int convert_time_t_to_formatted_string(time_t *time,char *buffer); +int get_expiration_time(char *expiration_duration, long int *expiration_seconds); // Global variables /*extern int socket_desc; Modified: trunk/pairing/common_headers.c ============================================================================== --- trunk/pairing/common_headers.c Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/common_headers.c Wed Aug 19 11:54:30 2009 (r824) @@ -7,6 +7,7 @@ * @file common_headers.c * @brief Common modules used for the pairing application. * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ @@ -54,66 +55,31 @@ */ void print_msg_info(int msg_type, int return_value) { - char msg_string[100]; + char msg_string[100]; - switch(msg_type) - { - case MSG_PASSWORD: - strcpy(msg_string, "password"); - break; - case MSG_ACK_1: - strcpy(msg_string, "ACK 1"); - break; - case MSG_PWD_REQUEST: - strcpy(msg_string, "password request"); - break; - case MSG_ACK_2: - strcpy(msg_string, "ACK 2"); - break; - case MSG_ERROR: - strcpy(msg_string, "error"); - break; - default: - strcpy(msg_string, "unknown"); - } - - DEBUG_MED("Message type: %s", msg_string); - DEBUG_MED("Return value: %d", return_value); - - return; -} - - -/** Converts a date in human-readable format to its time in seconds. - * - * @param expiration_date Pointer to the string containing the human-readable version. - * @param expiration_seconds Pointer to the long int where the result should be stored. - * - * @return 1 if successful; 0 if failed - */ -int get_expiration_time(char *expiration_date, long int *expiration_seconds) -{ - assert(expiration_date != NULL); - assert(expiration_seconds != NULL); - - DEBUG_HIGH("Parsing date."); + switch(msg_type) + { + case MSG_PASSWORD: + strcpy(msg_string, "password"); + break; + case MSG_ACK_1: + strcpy(msg_string, "ACK 1"); + break; + case MSG_PWD_REQUEST: + strcpy(msg_string, "password request"); + break; + case MSG_ACK_2: + strcpy(msg_string, "ACK 2"); + break; + case MSG_ERROR: + strcpy(msg_string, "error"); + break; + default: + strcpy(msg_string, "unknown"); + } - char *c; - struct tm time_offset; + DEBUG_MED("Message type: %s", msg_string); + DEBUG_MED("Return value: %d", return_value); - // Date format: dd-mm-yyyy hh:mm:ss (24 hour clock) - c = strptime((const char *)expiration_date, "%d-%m-%Y %H:%M:%S", &time_offset); - if ((c == NULL) || (*c != 0)) // If c does not point to the terminating character of the string - { // then strptime did not make it all of the way through the string. - DEBUG("Could not parse time-and-date string."); - return 0; - } - - DEBUG_HIGH("You specified: %s", asctime(&time_offset)); - - *expiration_seconds = (long int)mktime(&time_offset); - DEBUG_HIGH("Time in seconds: %ld", *expiration_seconds); - - return 1; + return; } - Modified: trunk/pairing/common_headers.h ============================================================================== --- trunk/pairing/common_headers.h Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/common_headers.h Wed Aug 19 11:54:30 2009 (r824) @@ -7,6 +7,7 @@ * @file common_headers.h * @brief Header file of common modules used for the pairing application. * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ @@ -89,6 +90,5 @@ // Function prototypes header_general* create_error_struct(int error_type, char *error_string); void print_msg_info(int msg_type, int return_value); -int get_expiration_time(char *expiration_duration, long int *expiration_seconds); #endif /* PISA_PAIR_COMMON_HEADERS_H */ Modified: trunk/pairing/libconfig_wrapper.c ============================================================================== --- trunk/pairing/libconfig_wrapper.c Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/libconfig_wrapper.c Wed Aug 19 11:54:30 2009 (r824) @@ -7,10 +7,18 @@ * @file libconfig_wrapper.c * @brief wrapper functions calling libconfig * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ #include "libconfig_wrapper.h" +#include "config.h" +#include "hitlist.h" +#include "packet_handler_accept.h" +#include "common.h" + +extern config_t authorized_cfg; +extern char *authorized_cfg_file; /** @todo Add a function which periodically scans files containing expiration dates and removes expired entries **/ @@ -24,62 +32,44 @@ */ int write_config(char *info, char *expiration, configtype type) { - config_t cfg; - config_setting_t *root; - - assert(info != NULL); - assert(expiration != NULL); - - config_init(&cfg); - if (!config_read_file(&cfg, FILE_AUTHORIZED_HOSTS)) - { - DEBUG("Could not read file \'%s\'.", FILE_AUTHORIZED_HOSTS); - return 0; - } - - root = config_root_setting(&cfg); - - switch(type) - { - case CONFIG_TYPE_HIT: - { - write_hit(&cfg, root, info, expiration); - break; - } - case CONFIG_TYPE_PWD: - { - config_setting_t *allowed_passwords; - config_setting_t *new_pwd_grp, *new_pwd, *new_expire; - - allowed_passwords = config_lookup(&cfg, "allowed_passwords"); - if (!allowed_passwords) - { - DEBUG_HIGH("List allowed_passwords did not previously exist. Creating..."); - allowed_passwords = config_setting_add(root, "allowed_passwords", CONFIG_TYPE_LIST); - } + assert(info != NULL); + assert(expiration != NULL); - // Add a new group - new_pwd_grp = config_setting_add(allowed_passwords, NULL, CONFIG_TYPE_GROUP); - // Add the password - new_pwd = config_setting_add(new_pwd_grp, "password", CONFIG_TYPE_STRING); - config_setting_set_string(new_pwd, info); - // Add the expiration date - new_expire = config_setting_add(new_pwd_grp, "expires", CONFIG_TYPE_STRING); - config_setting_set_string(new_expire, expiration); - - break; - } - default: - { - DEBUG("Invalid information type."); - return 0; - } - } + switch(type) + { + case CONFIG_TYPE_HIT: + { + add_hit(info, expiration); + break; + } + case CONFIG_TYPE_PWD: + { + config_setting_t *allowed_passwords; + config_setting_t *new_pwd_grp, *new_pwd, *new_expire; + + allowed_passwords = check_list("allowed_passwords"); + + // Add a new group + new_pwd_grp = config_setting_add(allowed_passwords, NULL, CONFIG_TYPE_GROUP); + // Add the password + new_pwd = config_setting_add(new_pwd_grp, "password", CONFIG_TYPE_STRING); + config_setting_set_string(new_pwd, info); + // Add the expiration date + new_expire = config_setting_add(new_pwd_grp, "expires", CONFIG_TYPE_STRING); + config_setting_set_string(new_expire, expiration); + + break; + } + default: + { + DEBUG("Invalid information type."); + return 0; + } + } - config_write_file(&cfg, FILE_AUTHORIZED_HOSTS); - config_destroy(&cfg); + pisa_cfg_write_authorized_hosts_file(); - return 1; + return 1; } @@ -149,97 +139,159 @@ return 1; } -/** Writes a HIT in the file VALID_HITS_FILE. If an entry already exists, it updates +/** Adds a HIT to the authorized hosts config. If an entry already exists, it updates * the expiration date. - * - * @param cfg The configuration from the config file. - * @param root The root config_setting_t for cfg. + * * @param info The HIT we wish to write. * @param expiration The expiration date to be written. * * @return 1 on success; 0 on failure */ -int write_hit(config_t *cfg, config_setting_t *root, char *info, char *expiration) +int add_hit(char *info, char *expiration) { - int hit_existed = 0; - config_setting_t *allowed_hosts; - config_setting_t *new_hit_grp, *new_hit, *new_expire; - config_setting_t *current_expiration; + int hit_existed = 0; + config_setting_t *allowed_hosts; + config_setting_t *new_hit_grp, *new_hit, *new_expire; + config_setting_t *current_expiration; + + pisa_hitlist_entry *con; + + if (!valid_addr(info)) + { + DEBUG("Tried to add invalid HIT \'%s\'. HIT not written. Exiting function.", info); + return 0; + } + + + con = find_hit_in_hitlist(info); + + if(con!=NULL) + { + hit_existed = 1; + current_expiration = config_setting_get_member(con->group, "expires"); + DEBUG("HIT found."); + } + + + if (hit_existed == 1) // Update old entry + { + DEBUG("Update expiration date for HIT"); + config_setting_set_string(current_expiration, expiration); + } + else // Create new entry + { + DEBUG("HIT not found"); + DEBUG("Adding new entry to config"); + + allowed_hosts = check_list("allowed_hosts"); + + // Add a new group + new_hit_grp = config_setting_add(allowed_hosts, NULL, CONFIG_TYPE_GROUP); + // Add the HIT + new_hit = config_setting_add(new_hit_grp, "hit", CONFIG_TYPE_STRING); + config_setting_set_string(new_hit, info); + // Add the expiration date + new_expire = config_setting_add(new_hit_grp, "expires", CONFIG_TYPE_STRING); + config_setting_set_string(new_expire, expiration); - if (!valid_addr(info)) - { - DEBUG("Tried to add invalid HIT \'%s\'. HIT not written. Exiting function.", info); - return 0; - } + } - allowed_hosts = config_lookup(cfg, "allowed_hosts"); - if (!allowed_hosts) - { - DEBUG_HIGH("List allowed_hosts did not previously exist. Creating..."); - allowed_hosts = config_setting_add(root, "allowed_hosts", CONFIG_TYPE_LIST); - } + return 1; +} - { // Iterate over the list - const char* hit_text = NULL; - int length = config_setting_length(allowed_hosts); - int i; - - for (i = 0; i < length; i++) - { - config_setting_t *group_element = NULL; - group_element = config_setting_get_elem(allowed_hosts, i); +/** Removes a HIT from the authorized hosts config. + * + * @param hit The HIT we wish to remove. + * + * @return 1 on success; 0 on failure; -1 on write error + */ +int remove_hit(char *hit) +{ + pisa_hitlist_entry *con; + config_setting_t *g,*parent; + char *name; + + con = find_hit_in_hitlist(hit); + + if(con!=NULL) + { + g=con->group; + parent= config_setting_parent(g); + name = (char *)config_setting_get_string(config_setting_get_member(g, "hit")); + + DEBUG("HIT: %s",name); + DEBUG("Removing HIT."); + + if(config_setting_remove_elem(parent,config_setting_index(g)) != CONFIG_TRUE) + { + DEBUG("Error removing HIT"); + } + + if(!pisa_cfg_write_authorized_hosts_file()) + { + return -1; + } - if (!group_element) - { - DEBUG("Error while parsing config file \'%s\'. Exiting function.", FILE_AUTHORIZED_HOSTS); - return 0; - } + return 1; + } - config_setting_t *this_hit = NULL; - this_hit = config_setting_get_member(group_element, "hit"); + return 0; +} - if (!this_hit) - { - DEBUG("Error extracting HIT from group %d in file %s. Exiting function.", i, FILE_AUTHORIZED_HOSTS); - return 0; - } +/** + * Searches for a HIT which is given in text format in the HITlist. + * + * @param hit The HIT we wish to find. + * + * @return The corresponding pisa_hitlist_entry if the HIT was found. Otherwise NULL. + */ +pisa_hitlist_entry *find_hit_in_hitlist(char *hit) +{ - hit_text = NULL; - hit_text = config_setting_get_string(this_hit); + pisa_hitlist_entry *con; + pisa_hitlist *hitlist_allowed_hosts; + struct sockaddr_in6 clientIp; + + config_setting_t *allowed_hosts; + allowed_hosts = check_list("allowed_hosts"); + hitlist_allowed_hosts = pisa_hitlist_build("allowed_hosts"); + inet_pton(AF_INET6,hit,&(clientIp.sin6_addr)); - if (hit_text != NULL && strlen(hit_text)>0) - DEBUG("HIT = %s", hit_text); - else - DEBUG("Error extracting HIT."); + // Checks if the HIT already exists to update the expiration date + con = pisa_hitlist_find(hitlist_allowed_hosts,&(clientIp.sin6_addr)); - if (identical_hits((char*)hit_text, info) == 1) - { - DEBUG("hit text = \'%s\'", hit_text); - DEBUG("info = \'%s\'", info); - hit_existed = 1; - current_expiration = config_setting_get_member(group_element, "expires"); - break; - } - - } + return con; +} - } +/** + * Checks if a list with list_name exists in the authorized hosts config. If not, the list will be created. + * @param list_name The list name + * @return A pointer to the list. + */ +config_setting_t *check_list(char * list_name) +{ + return check_list_in_config(list_name,&authorized_cfg); +} - if (hit_existed == 1) // Update old entry - { - config_setting_set_string(current_expiration, expiration); - } - else // Create new entry - { - // Add a new group - new_hit_grp = config_setting_add(allowed_hosts, NULL, CONFIG_TYPE_GROUP); - // Add the HIT - new_hit = config_setting_add(new_hit_grp, "hit", CONFIG_TYPE_STRING); - config_setting_set_string(new_hit, info); - // Add the expiration date - new_expire = config_setting_add(new_hit_grp, "expires", CONFIG_TYPE_STRING); - config_setting_set_string(new_expire, expiration); - } +/** + * Checks if a list with list_name exists in the given config. If not, the list will be created. + * @param list_name The list name + * @param config The config to check for the list + * + * @return A pointer to the list. + */ +config_setting_t *check_list_in_config(char * list_name, config_t *config) +{ + config_setting_t *root; + config_setting_t *list; - return 1; + list = config_lookup(config, list_name); + if (!list) + { + root = config_root_setting(config); + DEBUG_HIGH("List %s did not previously exist. Creating...",list_name); + list = config_setting_add(root, list_name, CONFIG_TYPE_LIST); + } + return list; } + Modified: trunk/pairing/libconfig_wrapper.h ============================================================================== --- trunk/pairing/libconfig_wrapper.h Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/libconfig_wrapper.h Wed Aug 19 11:54:30 2009 (r824) @@ -7,6 +7,7 @@ * @file libconfig_wrapper.h * @brief header file of wrapper functions calling libconfig * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ @@ -16,6 +17,7 @@ // This is a wrapper for the libconfig configuration file reader #include "common.h" #include <libconfig.h> +#include "hitlist.h" #define FILE_AUTHORIZED_HOSTS "authorized_hosts.cfg" @@ -26,6 +28,10 @@ // Function prototypes int write_config(char *info, char *expiration, configtype type); int get_config_setting(char *filename, char *path, int type, void *return_val, int strlen); -int write_hit(config_t *cfg, config_setting_t *root, char *info, char *expiration); +int add_hit(char *info, char *expiration); +config_setting_t *check_list(char * list_name); +config_setting_t *check_list_in_config(char * list_name, config_t *config); +pisa_hitlist_entry *find_hit_in_hitlist(char *hit); +int remove_hit(char *hit); #endif /* PISA_PAIR_LIBCONFIG_WRAPPER_H */ Added: trunk/pairing/management.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/pairing/management.c Wed Aug 19 11:54:30 2009 (r824) @@ -0,0 +1,1187 @@ +/* + * Copyright (c) 2009, Distributed Systems Group, RWTH Aachen + * All rights reserved. + */ + +/** + * @file management.c + * @brief Management tool for the server daemon. + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> + * @date Aug. 2009 + */ + +#include <stdio.h> +#include <unistd.h> +#include <time.h> +#include <netinet/in.h> +#include <search.h> +#include <signal.h> +#include <getopt.h> + +#include "global.h" /* it must be included before all other header files */ +#include "config.h" +#include "debug.h" +#include "common_headers.h" +#include "common.h" +#include "util.h" +#include "libconfig_wrapper.h" +#include "hitlist.h" +#include "management.h" + +extern config_t cfg; +management_conf managementconf; + +static const struct option longopts[] = + { + {"hit", required_argument, NULL, 'h'}, + {"expiration", required_argument, NULL, 'e'}, + {"remove", no_argument, NULL, 'r'}, + {"list", required_argument, NULL, 'l'}, + {"username", required_argument, NULL, 'u'}, + {"active", required_argument, NULL, 'a'}, + {"authorizedcfg", required_argument, NULL, 'f'}, + {"userscfg", required_argument, NULL, 'c'}, + {"relaycfg", required_argument, NULL, 's'}, + {"creditcard", required_argument, NULL, 'p'}, + {0, 0, 0, 0} + }; + +static int pisa_userlist_entry_compare_hit(const void *p1, const void *p2); +static int pisa_userlist_entry_compare_name(const void *p1, const void *p2); +static void pisa_user_hit_list_destroy(pisa_userhitlist *list); +static void pisa_userlist_destroy(pisa_userlist *list); +static void pisa_mgmt_conf_init(management_conf *m); +static pisa_userhitlist * pisa_merge_user_and_hit_list(pisa_userlist *ul, pisa_hitlist *hl); +static void pisa_userlist_parse(const struct cfg_group *g, void *user_data); +static void remove_leading_zeroes_from_hit(char *hit); +static int pisa_userlist_entry_remove(pisa_userlist_entry *entry); + +/** + * Frees the memory allocated for the user_hit_list + * @param list The user_hit_list which should be freed + */ +static void pisa_user_hit_list_destroy(pisa_userhitlist *list) +{ + if (!list) + { + return ; + } + + if (list->entries) + { + free(list->entries); + } + + free(list); +} + + +/** + * Frees the memory allocated for the userlist + * @param list The userlist which should be freed + */ +static void pisa_userlist_destroy(pisa_userlist *list) +{ + if (!list) + { + return ; + } + + if (list->entries) + { + free(list->entries); + } + + free(list); +} + +/** + * Comparing userlist_entries means comparing their HITs + */ +static int pisa_userlist_entry_compare_hit(const void *p1, const void *p2) +{ + + pisa_userlist_entry *e1 = (pisa_userlist_entry *) p1; + pisa_userlist_entry *e2 = (pisa_userlist_entry *) p2; + struct in6_addr hit1; + struct in6_addr hit2; + + inet_pton(PF_INET6, e1->hit, &hit1); + inet_pton(PF_INET6, e2->hit, &hit2); + + return pisa_ipv6_cmp(&hit1, &hit2); +} + +/** + * Comparing userlist_entries means comparing the user_names + */ +static int pisa_userlist_entry_compare_name(const void *p1, const void *p2) +{ + + pisa_userlist_entry *e1 = (pisa_userlist_entry *) p1; + pisa_userlist_entry *e2 = (pisa_userlist_entry *) p2; + + return strcmp((const char *)&e1->user_name, (const char *) &e2->user_name); +} + +/** + * Callback for the configIterateOverGroup function. + * will build our userlist. + * @param g config group in which hit value and other values will be obtained + * @param user_data user-defined data + */ +static void pisa_userlist_parse(const struct cfg_group *g, void *user_data) +{ + char buffer[1000]; + pisa_userlist *ul = (pisa_userlist *)user_data; + + if (!ul) + return ; + + ul->entries[ul->cur_slots].group = (config_setting_t *)g; + + pisa_cfg_get_group_string_value(g, "hit", buffer, sizeof(buffer)); + + + struct in6_addr addr; + + if (pisa_convert_string_to_address(buffer, &addr) != 0) + { + PISA_ERROR("Invalid network address string:<%s>\n", buffer); + } + else if (!ipv6_addr_is_hit(&addr)) + { + PISA_ERROR("Invalid network address string:<%s>\n", buffer); + } + else + { + strncpy(ul->entries[ul->cur_slots].hit, buffer, INET6_ADDRSTRLEN); + pisa_cfg_get_group_string_value(g, "user_name", buffer, sizeof(buffer)); + strncpy(ul->entries[ul->cur_slots].user_name, buffer, MAX_USERNAME_LENGTH); + ul->entries[ul->cur_slots].active = pisa_cfg_get_group_bool_value(g, "active"); + pisa_cfg_get_group_string_value(g,"credit_card",ul->entries[ul->cur_slots].creditcard,MAX_CREDIT_CARD_LENGTH); + ul->cur_slots++; + } + +} + +/** + * Merges the userlist and the hitlist to a pisa_userhitlist which can be printed out. + * @param ul Userlist which should be merged + * @param hl Hitlist which should be merged + * @return The merged list as an user_hit_list struct. + */ +static pisa_userhitlist * pisa_merge_user_and_hit_list(pisa_userlist *ul, pisa_hitlist *hl) +{ + if (!ul || !hl) + return NULL; + + int i, j; + char hit_tmp[INET6_ADDRSTRLEN]; + char buf_expiration[LENGTH_TIMEOUT]; + pisa_hitlist_entry *entry; + pisa_userlist_entry *ulentry; + pisa_userlist_entry ulentry2; + pisa_userhitlist *merged_list = malloc(sizeof(pisa_userhitlist)); + + merged_list->max_slots = ul->max_slots + hl->max_slots; + merged_list->cur_slots = 0; + merged_list->entries = calloc(sizeof(pisa_userhitlist_entry), merged_list->max_slots); + + i = 0; + j = 0; + + // Mergesort + while (i < ul->max_slots && j < hl->max_slots) + { + ulentry = &ul->entries[i]; + entry = &hl->entries[j]; + inet_ntop(AF_INET6, &(entry->hit), hit_tmp, INET6_ADDRSTRLEN); + memcpy(&ulentry2.hit, hit_tmp, sizeof(ulentry2.hit)); + + if (pisa_userlist_entry_compare_hit(ulentry, &ulentry2) <= 0) + { + + strncpy(merged_list->entries[merged_list->cur_slots].hit, ulentry->hit, INET6_ADDRSTRLEN); + strncpy(merged_list->entries[merged_list->cur_slots].user_name, ulentry->user_name, MAX_USERNAME_LENGTH); + merged_list->entries[merged_list->cur_slots].active = ulentry->active; + strncpy(merged_list->entries[merged_list->cur_slots].creditcard,ulentry->creditcard,MAX_CREDIT_CARD_LENGTH); + i++; + } + + if (pisa_userlist_entry_compare_hit(ulentry, &ulentry2) == 0) + { + convert_time_t_to_formatted_string(&entry->expiration, buf_expiration); + strncpy(merged_list->entries[merged_list->cur_slots].expiration, buf_expiration, LENGTH_TIMEOUT); + j++; + } + + if (pisa_userlist_entry_compare_hit(ulentry, &ulentry2) > 0) + { + strncpy(merged_list->entries[merged_list->cur_slots].hit, ulentry2.hit, INET6_ADDRSTRLEN); + convert_time_t_to_formatted_string(&entry->expiration, buf_expiration); + strncpy(merged_list->entries[merged_list->cur_slots].expiration, buf_expiration, LENGTH_TIMEOUT); + memset(merged_list->entries[merged_list->cur_slots].creditcard,0,sizeof(merged_list->entries[merged_list->cur_slots].creditcard)); + merged_list->entries[merged_list->cur_slots].active = 2; + j++; + } + + merged_list->cur_slots++; + } + + while (i < ul->max_slots) + { + ulentry = &ul->entries[i]; + strncpy(merged_list->entries[merged_list->cur_slots].hit, ulentry->hit, INET6_ADDRSTRLEN); + strncpy(merged_list->entries[merged_list->cur_slots].user_name, ulentry->user_name, MAX_USERNAME_LENGTH); + merged_list->entries[merged_list->cur_slots].active = ulentry->active; + strncpy(merged_list->entries[merged_list->cur_slots].creditcard,ulentry->creditcard,MAX_CREDIT_CARD_LENGTH); + i++; + merged_list->cur_slots++; + } + + while (j < hl->max_slots) + { + entry = &hl->entries[j]; + inet_ntop(AF_INET6, &(entry->hit), hit_tmp, INET6_ADDRSTRLEN); + strncpy(merged_list->entries[merged_list->cur_slots].hit, hit_tmp, INET6_ADDRSTRLEN); + convert_time_t_to_formatted_string(&entry->expiration, buf_expiration); + strncpy(merged_list->entries[merged_list->cur_slots].expiration, buf_expiration, LENGTH_TIMEOUT); + merged_list->entries[merged_list->cur_slots].active = 2; + memset(merged_list->entries[merged_list->cur_slots].creditcard,0,sizeof(merged_list->entries[merged_list->cur_slots].creditcard)); + j++; + merged_list->cur_slots++; + } + + return merged_list; +} + +/** + * Searches for a HIT which is given in text format in the userslist. + * + * @param ul The userlist where we search for the Hit + * @param hit The HIT we wish to find. + * + * @return The corresponding userlist_entry if the HIT was found. Otherwise NULL. + */ +pisa_userlist_entry *pisa_userlist_find_hit(const pisa_userlist *ul, + const char *hit) +{ + + pisa_userlist_entry s; + + if (!ul) + return 0; + + memcpy(&s.hit, hit, sizeof(s.hit)); + + return (pisa_userlist_entry *)bsearch(&s, ul->entries, ul->cur_slots, + + sizeof(pisa_userlist_entry), + pisa_userlist_entry_compare_hit); +} + + +/** + * Searches for a user_name in the userslist. + * + * @param ul The userlist where we search for the Hit + * @param name The user_name we wish to find. + * + * @return The corresponding userlist_entry if the HIT was found. Otherwise NULL. + */ +pisa_userlist_entry *pisa_userlist_find_username(const pisa_userlist *ul, const char *name) +{ + + pisa_userlist_entry s; + + if (!ul) + return 0; + + memcpy(&s.user_name, name, sizeof(s.user_name)); + + // lfind because userlist is sorted by HIT + return (pisa_userlist_entry *)lfind(&s, ul->entries, (size_t *) &ul->cur_slots, + + sizeof(pisa_userlist_entry), + pisa_userlist_entry_compare_name); +} + + +/** + * Builds userlist with userlist_entry from the given section + * + * @param section The section which is used to build the userslist + * + * @return The corresponding userlist + */ +pisa_userlist *pisa_userlist_build(const char *section) +{ + assert(section != NULL); + + pisa_userlist *ul = malloc(sizeof(pisa_userlist)); + config_setting_t *list; + list = check_list_in_config("users", &cfg); + + ul->max_slots = pisa_cfg_get_number_of_section_entries(section, &cfg); + ul->cur_slots = 0; + + ul->entries = calloc(sizeof(pisa_userlist_entry), ul->max_slots); + + pisa_cfg_iterate_group(list, pisa_userlist_parse, ul); + + /* sort our array - so we can use bsearch to find a matching hit */ + qsort(ul->entries, ul->cur_slots, sizeof(pisa_userlist_entry), + pisa_userlist_entry_compare_hit); + + return ul; +} + +/** Main program that will be run on the user's computer. + */ +int main(int argc, char *argv[]) +{ + int result; + + struct options options = { 0 }; + pisa_hitlist *hitlist_allowed_hosts = NULL; + pisa_hitlist_entry *entry = NULL; + pisa_userlist *userlist = NULL; + pisa_userlist_entry *ulentry = NULL; + pisa_userhitlist *merged_list = NULL; + pisa_userhitlist_entry *uhlentry = NULL; + pisa_userhitlist_entry new_entry = {}; + + pisa_mgmt_conf_init(&managementconf); + + new_entry.active = NO_CHANGE; + + if (!pisa_mgmt_parse_options(argc, argv, &new_entry, &managementconf, &options)) + { + return ERROR_PARSING_COMMANDLINE; + } + + // Initialize Configs + if (!pisa_cfg_authorized_hosts_setup_file(managementconf.authorizedcfgfile)) + { + return ERROR_OPENING_CONFIG; + } + if (!pisa_cfg_setup_file(managementconf.userscfgfile)) + { + return ERROR_OPENING_CONFIG; + } + + switch (options.mode) + { + // Different list-modes + case LIST_SINGLE_ONLY_HIT: + entry = find_hit_in_hitlist(new_entry.hit); + + if (!NULL) + { + pisa_hitlist_entry_print(entry, options.list_mode); + } + + break; + + case LIST_ALL: + userlist = pisa_userlist_build(USERS_SECTION); + hitlist_allowed_hosts = pisa_hitlist_build("allowed_hosts"); + merged_list = pisa_merge_user_and_hit_list(userlist, hitlist_allowed_hosts); + int i; + + for (i = 0;i < merged_list->cur_slots;i++) + { + uhlentry = &merged_list->entries[i]; + pisa_userhitlist_entry_print(uhlentry, options.list_mode); + } + + pisa_user_hit_list_destroy(merged_list); + break; + + case LIST_SINGLE: + userlist = pisa_userlist_build(USERS_SECTION); + ulentry = pisa_userlist_find_username(userlist, new_entry.user_name); + + if (ulentry != NULL) + { + pisa_userlist_entry_print(ulentry, options.list_mode); + } + + break; + + // Different remove-modes + + case REMOVE_ONLY_HIT: + // Remove Hit + result = remove_hit(new_entry.hit); + + if (result <= 0) + { + if (result == 0) + { + result = ERROR_NOT_FOUND; + } + else + { + result = ERROR_WRITING_CONFIG; + } + + PISA_ERROR("Error removing HIT.\n"); + } + + break; + + case REMOVE: + // Remove Hit and Users entry + // Only Username was given + + if (new_entry.hit[0] == '\0') + { + userlist = pisa_userlist_build(USERS_SECTION); + ulentry = pisa_userlist_find_username(userlist, new_entry.user_name); + + if (ulentry != NULL) + { + strncpy(new_entry.hit, ulentry->hit, INET6_ADDRSTRLEN); + } + else + { + PISA_ERROR("Username not found!\n"); + result = ERROR_NOT_FOUND; + break; + } + } + + result = pisa_mgmt_remove_userlist_entry_by_hit(new_entry.hit); + + if (result <= 0) + { + if (result == 0) + { + result = ERROR_GENERAL; + } + else + { + result = ERROR_WRITING_CONFIG; + } + } + else + { + if (ulentry->active) + { + result = remove_hit(new_entry.hit); + + if (result <= 0) + { + if (result == 0) + { + result = ERROR_NOT_FOUND; + } + else + { + result = ERROR_WRITING_CONFIG; + } + + PISA_ERROR("Error removing HIT.\n"); + } + } + } + + break; + + // Different add-modes + + case ADD_OR_EDIT_ONLY_HIT: + // No username was given + result = write_config(new_entry.hit, new_entry.expiration, CONFIG_TYPE_HIT); + + if (!result) + { + result = ERROR_WRITING_CONFIG; + } + + break; + + case ADD_OR_EDIT: + // Find HIT through users config + if (new_entry.hit[0] == '\0') + { + userlist = pisa_userlist_build(USERS_SECTION); + ulentry = pisa_userlist_find_username(userlist, new_entry.user_name); + + if (ulentry != NULL) + { + strncpy(new_entry.hit, ulentry->hit, INET6_ADDRSTRLEN); + } + else + { + PISA_ERROR("Username not found!\n"); + result = ERROR_NOT_FOUND; + break; + } + + }else + { + if(new_entry.creditcard[0] == '\0') + { + PISA_ERROR("No Creditcard given"); + pisa_mgmt_print_usage(argv); + result = ERROR_PARSING_COMMANDLINE; + break; + } + } + + result = pisa_mgmt_users_config_write(&new_entry); + + if (result <= 0) + { + if (result == 0) + { + result = ERROR_GENERAL; + } + else + { + result = ERROR_WRITING_CONFIG; + } + } + + break; + + default: + PISA_ERROR("Unknown error occurred.\n"); + return ERROR_GENERAL; + break; + } + + // Free lists + pisa_hitlist_destroy(hitlist_allowed_hosts); + pisa_userlist_destroy(userlist); + + // Config cleanup + pisa_cfg_cleanup(); + pisa_cfg_authorized_hosts_cleanup(); + + result = (result == 1) ? 0 : result; + + return result; +} + +/** + * Initializes the management_conf struct + * @param m Pointer to the management_conf struct + */ +static void pisa_mgmt_conf_init(management_conf *m) +{ + assert(m != NULL); + + memset(m->userscfgfile, 0, sizeof(m->userscfgfile)); + memset(m->authorizedcfgfile, 0, sizeof(m->authorizedcfgfile)); +} + +/** + * Print usage instructions of management software. + * + * @param argv pointer to the array of command arguments + */ +void pisa_mgmt_print_usage(char **argv) +{ + PISA_ERROR("\nUSAGE:\n" + "%s -l <0|1> [-u <username>|-h <hit>]\n" + "%s -r [-u <username>|-h <hit>]\n" + "%s -h <hit> -e <1|\"YYYY-MM-DD HH:MM:SS\">\n" + "%s -u <username> [-h <hit>] [-e <1|\"YYYY-MM-DD HH:MM:SS\">] [-a <0|1>]\n" + "\n" + "%s -f <authorizedconfig>,\n" + "%s -c <usersconfig> and\n" + "%s -s <relay_config> can always be used to use specific config paths\n" + "%s -p <creditcard> \n" + "\n" + "Options:\n" + "-h|--hit HIT \t\t\t\t: HIT of the client\n" + "-e|--expiration <1|\"Expiration Date\"> \t:\n" + "\t\t\t\t\t 1: default expiration date\n" + "\t\t\t\t\t Expiration date in format YYYY-MM-DD HH:MM:SS\n" + "-r|--remove \t\t\t\t: Remove given HIT or given User\n" + "-l|--list <0|1>\t\t\t\t: 0: normal mode, 1: short mode\n" + "\t\t\t\t\t: List given HIT or given user or all entries\n" + "-p|--creditcard <creditcard> Credit card which is needed for new users\n" + "-a|--authorizedcfg <authorizedconfig>\t: Path to authorized_hosts configuration file\n" + "-f|--userscfg <usersconfig>\t\t: Path to users configuration file\n" + "-s|--relaycfg <relayconfig>\t\t: Path to relay configuration file\n" + "\n\n" + "Examples: \n" + "\t%s -h 2001:1c:539b:fd3:ebd7:de72:7b12:9ba7\n" + "Or: \t%s -h 2001:1c:539b:fd3:ebd7:de72:7b12:9ba7 -e \"2009-07-12 12:00:00\"\n" + "Or: \t%s -h 2001:1c:539b:fd3:ebd7:de72:7b12:9ba7 -e 1\n" + "Or: \t%s -h 2001:1c:539b:fd3:ebd7:de72:7b12:9ba7 -r \n" + "Or: \t%s -h 2001:1c:539b:fd3:ebd7:de72:7b12:9ba7 -l 0\n" + "Or: \t%s -h 2001:1c:539b:fd3:ebd7:de72:7b12:9ba7 -u john -e1\n" + "Or: \t%s -u john -a 0 (If user john already exists.)\n" + "Or: \t%s -u john -e 1 (If user john already exists.)\n" + "Or: \t%s -l 0\n" + , argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], + argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], argv[0], + argv[0], argv[0], argv[0]); +} + +/** This function parses the command line input options and stores in the information accordingly. + * + * @param argc The argument counter. + * @param argv The arguments array. + * @param new_entry Pointer to the user_hit_list_entry for storing the parsed details. + * @param mconf Pointer to the management configuration structure. + * @param options Pointer to the options struct. + * + * @return 1 if parsing successful and required arguments are present + * @return 0 otherwise (recommend exit program) + */ +int pisa_mgmt_parse_options(int argc, char *argv[], pisa_userhitlist_entry *new_entry, + management_conf *mconf, struct options *options) +{ + int sw; + int temp; + int hit_given = 0; + int expiration_given = 0; + int remove = 0; + int list = 0; + int username_given = 0; + int option_index = 0; + int relay_cfg_path_given = 0; + int usercfg_given = 0; + int authorizedcfg_given = 0; + int credit_card_given = 0; + char relay_cfg_file[MAX_PATH]; + struct in6_addr addr; + + // Parse options + while ((sw = getopt_long(argc, argv, OPTION_STRING, longopts, &option_index)) != -1) + { + switch (sw) + { + case ':': /* missing argument of a parameter */ + PISA_ERROR("Missing argument."); + return 0; + + case 'h': + + if (pisa_convert_string_to_address(optarg, &addr) != 0) + { + return 0; + } + + if (!ipv6_addr_is_hit(&addr)) + { + PISA_ERROR("Provided address is not a HIT\n"); + return 0; + } + + strncpy(new_entry->hit, optarg, INET6_ADDRSTRLEN); + // :0ba8 will be replaced with :ba8 + // Thus, no problems will arise because the userlist + // just uses strings to save the hit address + remove_leading_zeroes_from_hit(new_entry->hit); + hit_given = 1; + break; + + case 'e': + // Use default expiration date + if (atoi(optarg) == 1) + { + expiration_given = USE_DEFAULT_EXPIRATION; + } + + // Use given expiration date + else + { + struct tm tm; + + if (!valid_date_string(optarg, &tm)) + { + PISA_ERROR("Provided date is not in the format: YYYY-MM-DD HH:MM:SS"); + return 0; + } + + strncpy(new_entry->expiration, optarg, LENGTH_TIMEOUT); + expiration_given = 1; + } + + break; + + case 'r': + remove = 1; + break; + + case 'l': + list = 1; + temp = atoi(optarg); + + if (temp >= 0 && temp <= 1) + { + options->list_mode = temp; + } + + break; + + case 'a': + temp = atoi(optarg); + + if (temp >= 0 && temp <= 1) + { + new_entry->active = temp; + } + + break; + + case 'p': + strncpy(new_entry->creditcard,optarg,MAX_CREDIT_CARD_LENGTH); + credit_card_given = 1; + break; + + case 'u': + strncpy(new_entry->user_name, optarg, MAX_USERNAME_LENGTH); + username_given = 1; + break; + + case 'f': + authorizedcfg_given = 1; + strncpy(mconf->authorizedcfgfile, optarg, MAX_PATH); + break; + + case 's': + relay_cfg_path_given = 1; + strncpy(relay_cfg_file, optarg, MAX_PATH); + break; + + case 'c': + usercfg_given = 1; + strncpy(mconf->userscfgfile, optarg, MAX_PATH); + break; + + default: /* unknown */ + pisa_mgmt_print_usage(argv); + return 0; + } + } + + // Use default value + if (!usercfg_given) + { + strcpy(mconf->userscfgfile, DEFAULT_USERS_CONFIG_FILE); + } + + // Use default value + if (!authorizedcfg_given) + { + strcpy(mconf->authorizedcfgfile, DEFAULT_AUTHORIZED_HOSTS_FILE); + } + + // No mode was given + if (!list && !expiration_given && !remove && new_entry->active == NO_CHANGE) + { + PISA_ERROR("No mode was given.\n"); + pisa_mgmt_print_usage(argv); + return 0; + } + // Mode was given + else + { + // No HIT or Username given + if (!hit_given && !username_given && !list) + { + PISA_ERROR("No HIT or Username given.\n"); + pisa_mgmt_print_usage(argv); + return 0; + } + + // Modes cannot be combined + if ((list && (remove || expiration_given || new_entry->active != NO_CHANGE)) || + (remove && (expiration_given || new_entry->active != NO_CHANGE)) || + (expiration_given && new_entry->active == NO_CHANGE && !hit_given && !username_given)) + { + PISA_ERROR("Modes cannot be combined.\n"); + pisa_mgmt_print_usage(argv); + return 0; + } + } + + // Decide which list-mode to use + if (list) + { + if (username_given) + { + options->mode = LIST_SINGLE; + return 1; + } + else if (hit_given) + { + options->mode = LIST_SINGLE_ONLY_HIT; + return 1; + } + else + { + options->mode = LIST_ALL; + return 1; + } + } + + // Decide which remove-mode to use + if (remove) + { + if (username_given) + { + options->mode = REMOVE; + return 1; + } + else + { + options->mode = REMOVE_ONLY_HIT; + return 1; + } + } + + // Use default expiration time + if (expiration_given == USE_DEFAULT_EXPIRATION) + { + PISA_INFO("Using default expiration.\n"); + // Use default relays_config.cfg in PWD + if (!relay_cfg_path_given) + { + if (!get_default_expiration(new_entry->expiration)) + { + return 0; + } + } + else + { + // Use given path + if (!get_default_expiration_from_config(new_entry->expiration, relay_cfg_file)) + { + return 0; + } + } + } + + // No expiration given + if (new_entry->active == ACTIVATED && !expiration_given) + { + PISA_ERROR("Either use -e 1 for default expiration or give a valid expiration date.\n"); + pisa_mgmt_print_usage(argv); + return 0; + } + + + // If the username was given the default ADD_OR_EDIT mode is used + // otherwise ADD_OR_EDIT_ONLY_HIT is used + if (!username_given) + { + options->mode = ADD_OR_EDIT_ONLY_HIT; + } + + // Everything was fine + return 1; +} + +/** + * Prints an hitlistEntry in normal or short mode + * + * @param entry Pointer to the hitlistEntry which should be printed + * @param list_mode The mode in which the entry is printed + */ +void pisa_hitlist_entry_print(pisa_hitlist_entry *entry, enum list_mode list_mode) +{ + if (entry != NULL) + { + char hit[INET6_ADDRSTRLEN]; + char buf_expiration[LENGTH_TIMEOUT]; + + inet_ntop(AF_INET6, &(entry->hit), hit, INET6_ADDRSTRLEN); + convert_time_t_to_formatted_string(&entry->expiration, buf_expiration); + + switch (list_mode) + { + case SHORT: + printf("%s\n", hit); + printf("%s\n", buf_expiration); + break; + + case NORMAL: + default: + printf("Address: %s\n", hit); + printf("Expiration: %s\n", buf_expiration); + printf("==================\n"); + break; + } + } +} + +/** + * Prints an userlist_entry in normal or short mode + * + * @param entry Pointer to the hitlistEntry which should be printed + * @param list_mode The mode in which the entry is printed + */ +void pisa_userlist_entry_print(pisa_userlist_entry *entry, enum list_mode list_mode) +{ + if (entry != NULL) + { + switch (list_mode) + { + + case SHORT: + printf("%s\n", (char *)&entry->user_name); + printf("%s\n", (char *)&entry->hit); + printf("%i\n", entry->active); + printf("%s\n",(char *)&entry->creditcard); + break; + + case NORMAL: + default: + printf("Username: %s\n", (char *)&entry->user_name); + printf("HIT: %s\n", (char *)&entry->hit); + printf("Active: %i\n", entry->active); + printf("Credit Card: %s\n",(char *)&entry->creditcard); + printf("==================\n"); + break; + } + } +} + +/** + * Prints an user_hit_list_entry in normal or short mode + * + * @param entry Pointer to the user_hit_list_entry which should be printed + * @param list_mode The mode in which the entry is printed + */ +void pisa_userhitlist_entry_print(pisa_userhitlist_entry *entry, enum list_mode list_mode) +{ + if (entry != NULL) + { + switch (list_mode) + { + + case SHORT: + PRINT_ENTRY(1,"%s\n", (char *)&entry->user_name); + PRINT_ENTRY(1,"%s\n", (char *)&entry->hit); + PRINT_ENTRY(entry->active != 2,"%i\n", entry->active ); + PRINT_ENTRY(entry->expiration != 0,"%s\n", (char *)&entry->expiration); + PRINT_ENTRY(entry->creditcard[0] != '\0',"%s\n",(char *)&entry->creditcard); + break; + + case NORMAL: + default: + PRINT_ENTRY(1,"Username: %s\n", (char *)&entry->user_name); + PRINT_ENTRY(1,"HIT: %s\n", (char *)&entry->hit); + PRINT_ENTRY(entry->active != 2,"Active: %i\n", entry->active ); + PRINT_ENTRY(entry->expiration != 0,"Expiration: %s\n", (char *)&entry->expiration); + PRINT_ENTRY(entry->creditcard[0] != '\0',"Credit Card: %s\n",(char *)&entry->creditcard); + printf("==================\n"); + break; + } + } +} + +/** Writes the users configuration. + * + * @param hit HIT + * @param user_name User_name + * @param expiration Expiration of the Hit + * @param active The active status of the Entry (0: Deactivated, 1:Activated, 2:No Change) + * + * @return 0 on failure; 1 on success; -1 on write error + */ +int pisa_mgmt_users_config_write(pisa_userhitlist_entry *new_entry) +{ + pisa_userlist *ul; + pisa_userlist_entry *entry; + int hit_existed = 0; + int old_active; + int result = 1; + config_setting_t *current_username; + config_setting_t *current_active; + config_setting_t *users_list; + config_setting_t *new_grp, *new_hit, *new_username, *new_active, *new_creditcard; + + ul = pisa_userlist_build(USERS_SECTION); + + entry = pisa_userlist_find_hit(ul, new_entry->hit); + + if (entry != NULL) + { + hit_existed = 1; + current_username = config_setting_get_member(entry->group, "user_name"); + current_active = config_setting_get_member(entry->group, "active"); + old_active = config_setting_get_bool(current_active); + } + + if (hit_existed) + { + if (new_entry->active != 2) + { + DEBUG("Changed active status."); + config_setting_set_bool(current_active, new_entry->active); + + // Add or Remove HIT from authorized_hosts.cfg because active changed + if (old_active != new_entry->active) + { + if (new_entry->active) + { + if (!write_config(new_entry->hit, new_entry->expiration, CONFIG_TYPE_HIT)) + { + result = -1; + } + } + else + { + result = remove_hit(new_entry->hit); + } + } + } + else + { + // Change expiration date + if (new_entry->active) + { + if (!write_config(new_entry->hit, new_entry->expiration, CONFIG_TYPE_HIT)) + { + result = -1; + } + } + } + } + else + { + PISA_INFO("HIT not found"); + PISA_INFO("Adding new entry to config"); + + users_list = check_list_in_config(USERS_SECTION, &cfg); + // Add a new group + new_grp = config_setting_add(users_list, NULL, CONFIG_TYPE_GROUP); + // Add the HIT + new_hit = config_setting_add(new_grp, "hit", CONFIG_TYPE_STRING); + config_setting_set_string(new_hit, new_entry->hit); + // Add the user_name + new_username = config_setting_add(new_grp, "user_name", CONFIG_TYPE_STRING); + config_setting_set_string(new_username, new_entry->user_name); + // Add active + new_entry->active = (new_entry->active != 0 ) ? 1 : 0; + new_active = config_setting_add(new_grp, "active", CONFIG_TYPE_BOOL); + config_setting_set_bool(new_active, new_entry->active); + // Add creditcard + new_creditcard = config_setting_add(new_grp,"credit_card",CONFIG_TYPE_STRING); + config_setting_set_string(new_creditcard,new_entry->creditcard); + + if (new_entry->active) + { + if (!write_config(new_entry->hit, new_entry->expiration, CONFIG_TYPE_HIT)) + { + result = -1; + } + } + } + + if (config_write_file(&cfg, managementconf.userscfgfile) != CONFIG_TRUE) + { + result = -1; + } + + pisa_userlist_destroy(ul); + + return result; +} + +/** + * Removes a user_entry from the users configuration file + * + * @param hit Search for the entry by the given Hit. + * + * @return 0-> Error, 1-> Success, -1 -> Write error + */ +int pisa_mgmt_remove_userlist_entry_by_hit(char *hit) +{ + + pisa_userlist *ul; + pisa_userlist_entry *entry; + int result = 0; + + ul = pisa_userlist_build(USERS_SECTION); + entry = pisa_userlist_find_hit(ul, hit); + + if (entry != NULL) + { + result = pisa_userlist_entry_remove(entry); + } + + pisa_userlist_destroy(ul); + return result; +} + +/** + * Removes a user_entry from the users configuration file + * + * @param name Search for the entry by the given username. + * + * @return 0-> Error, 1-> Success + */ +int pisa_mgmt_remove_userlist_entry_by_name(char *name) +{ + pisa_userlist *ul; + pisa_userlist_entry *entry; + int result = 0; + + ul = pisa_userlist_build(USERS_SECTION); + entry = pisa_userlist_find_username(ul, name); + + if (entry != NULL) + { + result = pisa_userlist_entry_remove(entry); + } + + pisa_userlist_destroy(ul); + return result; +} + +/** + * Removes a user_entry from the users configuration file + * + * @param entry Remove the given userlist_entry. + * + * @return 0-> Error, 1-> Success, -1 Write error + */ +static int pisa_userlist_entry_remove(pisa_userlist_entry *entry) +{ + config_setting_t *group; + config_setting_t *parent; + + if (!entry) + { + return 0; + } + + group = entry->group; + parent = config_setting_parent(group); + + if (config_setting_remove_elem(parent, config_setting_index(group)) != CONFIG_TRUE) + { + DEBUG("Error removing HIT"); + return 0; + } + + if (config_write_file(&cfg, managementconf.userscfgfile) != CONFIG_TRUE) + { + return -1; + } + + return 1; +} + +/** + * Remove zeroes from HITs :0ba8 becomes :ba8 + * @param hit Pointer to the HIT from which the zeroes should be removed + */ +static void remove_leading_zeroes_from_hit(char *hit) +{ + struct sockaddr_in6 hit_addr; + inet_pton(PF_INET6, hit, &(hit_addr.sin6_addr)); + inet_ntop(AF_INET6, &(hit_addr.sin6_addr), hit, INET6_ADDRSTRLEN); +} Added: trunk/pairing/management.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/pairing/management.h Wed Aug 19 11:54:30 2009 (r824) @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2009, Distributed Systems Group, RWTH Aachen + * All rights reserved. + */ + +/** + * @file management.c + * @brief Management tool for the server daemon. + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> + * @date Aug. 2009 + */ + +#ifndef MANAGEMENT_H_ +#define MANAGEMENT_H_ + +#define MAX_USERNAME_LENGTH 100 +#define MAX_CREDIT_CARD_LENGTH 20 + +#define USERS_SECTION "users" +#define DEFAULT_USERS_CONFIG_FILE "users.conf" +#define DEFAULT_AUTHORIZED_HOSTS_FILE "authorized_hosts.conf" + +#define ERROR_OPENING_CONFIG 2 +#define ERROR_NOT_FOUND 3 +#define ERROR_PARSING_COMMANDLINE 4 +#define ERROR_WRITING_CONFIG 5 +#define ERROR_GENERAL 6 + +#define DEACTIVATED 0 +#define ACTIVATED 1 +#define NO_CHANGE 2 + +/** This macro prints the given expression if true + * or a new line otherwise + */ +#define PRINT_ENTRY(func,fmt,args...) \ + if(func) {\ + printf( fmt , ## args);\ + }else{ \ + printf("\n"); \ + } + +#define USE_DEFAULT_EXPIRATION 2 + +#define OPTION_STRING "h:e:rl:u:a:f:c:s:p:" + +extern config_t authorized_cfg; + +enum mode {ADD_OR_EDIT,ADD_OR_EDIT_ONLY_HIT,REMOVE,REMOVE_ONLY_HIT,LIST_SINGLE,LIST_SINGLE_ONLY_HIT,LIST_ALL}; +enum list_mode {NORMAL,SHORT}; + +typedef struct +{ + char hit[INET6_ADDRSTRLEN]; + char user_name[MAX_USERNAME_LENGTH]; + int active; + char expiration[LENGTH_TIMEOUT]; + char creditcard[MAX_CREDIT_CARD_LENGTH]; +} pisa_userhitlist_entry; + +typedef struct +{ + char hit[INET6_ADDRSTRLEN]; + config_setting_t *group; + char user_name[MAX_USERNAME_LENGTH]; + int active; + char creditcard[MAX_CREDIT_CARD_LENGTH]; +} pisa_userlist_entry; + +typedef struct +{ + pisa_userhitlist_entry *entries; + int max_slots; + int cur_slots; + +} pisa_userhitlist; + +typedef struct +{ + pisa_userlist_entry *entries; + int max_slots; + int cur_slots; +} pisa_userlist; + +struct options +{ + enum mode mode; + enum list_mode list_mode; +}; + +typedef struct +{ + char userscfgfile[MAX_PATH]; + char authorizedcfgfile[MAX_PATH]; +} management_conf; + +void pisa_mgmt_print_usage(char *argv[]); +int pisa_mgmt_parse_options(int argc, char *argv[],pisa_userhitlist_entry *new_entry, + management_conf *mconf,struct options *options); +pisa_userlist *pisa_userlist_build(const char *section); +void pisa_userlist_entry_print(pisa_userlist_entry *entry,enum list_mode list_mode); +void pisa_hitlist_entry_print(pisa_hitlist_entry *entry,enum list_mode list_mode); +void pisa_userhitlist_entry_print(pisa_userhitlist_entry *entry,enum list_mode list_mode); +int pisa_mgmt_users_config_write(pisa_userhitlist_entry *new_entry); +int pisa_mgmt_remove_userlist_entry_by_hit(char *hit); +int pisa_mgmt_remove_userlist_entry_by_name(char *name); + +#endif /*MANAGEMENT_H_*/ Modified: trunk/pairing/packet_handler_accept.c ============================================================================== --- trunk/pairing/packet_handler_accept.c Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/packet_handler_accept.c Wed Aug 19 11:54:30 2009 (r824) @@ -7,9 +7,13 @@ * @file packet_handler_accept.c * @brief post-accept process functions for packet handlers * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ +#include "global.h" /* it must be included before all other header files */ +#include "config.h" +#include "hitlist.h" #include "packet_handler_accept.h" @@ -22,79 +26,53 @@ */ int handle_packet_password(struct sockaddr_in6 *socket_addr, header_password *hdr_pwd) { - int pwd_valid; - header_general *gen_hdr; - DEBUG_HIGH("Handling a password packet..."); + int pwd_valid; + header_general *gen_hdr; + DEBUG_HIGH("Handling a password packet..."); + + assert(socket_addr != NULL); + assert(hdr_pwd != NULL); + + pwd_valid = check_password((char*)&(hdr_pwd->password)); + + if (pwd_valid) + { + DEBUG_HIGH("Valid password."); + // Create ack_1 packet + gen_hdr = create_ack_1_struct(); + } + else // Transmit an error message + { + DEBUG_HIGH("Invalid password."); + gen_hdr = create_error_struct(ERROR_INVALID_PWD, "Invalid password. Please try again."); + } + + CHECK_FOR_NULL_HDR(gen_hdr); + + // Transmit message + SENDTO(global_accept.socket_desc, socket_addr, gen_hdr); + + free(gen_hdr); + + if (pwd_valid) + DEBUG_MED("ACK 1 message sent successfully."); + else + DEBUG_MED("Error message sent successfully."); - assert(socket_addr != NULL); - assert(hdr_pwd != NULL); - - pwd_valid = check_password((char*)&(hdr_pwd->password)); - - if (pwd_valid) - { - DEBUG_HIGH("Valid password."); - // Create ack_1 packet - gen_hdr = create_ack_1_struct(); - } - else // Transmit an error message + if (pwd_valid) + { // Write the user down in our database + char hit[INET6_ADDRSTRLEN]; + char buf_expiration[LENGTH_TIMEOUT]; + if(!get_default_expiration(buf_expiration)) { - DEBUG_HIGH("Invalid password."); - gen_hdr = create_error_struct(ERROR_INVALID_PWD, "Invalid password. Please try again."); + return 0; } - CHECK_FOR_NULL_HDR(gen_hdr); - - // Transmit message - SENDTO(global_accept.socket_desc, socket_addr, gen_hdr); - - free(gen_hdr); - - if (pwd_valid) - DEBUG_MED("ACK 1 message sent successfully."); - else - DEBUG_MED("Error message sent successfully."); - - if (pwd_valid) - { // Write the user down in our database - char hit[INET6_ADDRSTRLEN]; - long int default_expiration_int; - int temp; - - time_t expiration; - struct tm *ts; - char buf_expiration[LENGTH_TIMEOUT]; - - // Obtain the default expiration for a master-password-based connection (in minutes) - temp = get_config_setting(FILE_SERVER_CONFIG, "connection_settings.default_connection_expiration", - CONFIG_TYPE_INT, &default_expiration_int, 0); - if (temp == 0) // Something failed in reading, debug printed by get_config_setting - { - DEBUG("User not remembered."); - return 0; - } - if (default_expiration_int == 0) - { - DEBUG("Could not read setting \'connection_settings.default_connection_expiration\' in file %s", FILE_SERVER_CONFIG); - DEBUG("User not remembered."); - return 0; - } - - default_expiration_int *= 60; // Convert to seconds - - time(&expiration); - expiration += default_expiration_int; // Add default expiration to current time - - // Convert to format: yyyy-mm-dd_hh:mm:ss - ts = localtime(&expiration); - strftime(buf_expiration, sizeof(buf_expiration), EXPIRATION_DATE_FORMAT, ts); - DEBUG_HIGH("Expiration: %s", (char *) &buf_expiration); + inet_ntop(AF_INET6, &socket_addr->sin6_addr, hit, sizeof(hit)); + write_config(hit, buf_expiration, CONFIG_TYPE_HIT); + } - inet_ntop(AF_INET6, &socket_addr->sin6_addr, hit, sizeof(hit)); - write_config(hit, buf_expiration, CONFIG_TYPE_HIT); - } - - return 1; + return 1; } @@ -107,41 +85,47 @@ */ int handle_packet_pwd_request(struct sockaddr_in6 *socket_addr, header_pwd_request *hdr_pwd_request) { - assert(socket_addr != NULL); - assert(hdr_pwd_request != NULL); + pisa_hitlist *allowed_hosts; + pisa_hitlist_entry *con; - header_general *gen_hdr; - char password[LENGTH_PASSWORD]; - char hit[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(socket_addr->sin6_addr), hit, sizeof(hit)); + assert(socket_addr != NULL); + assert(hdr_pwd_request != NULL); - if (!is_allowed_hit(hit)) - { - gen_hdr = create_error_struct(ERROR_NOT_CONNECTED, "Sorry, but that HIT is not authenticated on this relay."); - CHECK_FOR_NULL_HDR(gen_hdr); + header_general *gen_hdr; + char password[LENGTH_PASSWORD]; - // Transmit message - SENDTO(global_accept.socket_desc, socket_addr, gen_hdr); + // Check if HIT is in allowed_hosts list + allowed_hosts = pisa_hitlist_build("allowed_hosts"); + con = pisa_hitlist_find(allowed_hosts,&socket_addr->sin6_addr); + + if(!con) + { + gen_hdr = create_error_struct(ERROR_NOT_CONNECTED, "Sorry, but that HIT is not authenticated on this relay."); + CHECK_FOR_NULL_HDR(gen_hdr); - free(gen_hdr); + // Transmit message + SENDTO(global_accept.socket_desc, socket_addr, gen_hdr); - return 0; - } + free(gen_hdr); - if (!store_pwd((char*)hdr_pwd_request->nickname, hdr_pwd_request->expiration1, hdr_pwd_request->expiration2, password)) - return 0; + return 0; + } - // Create password ack structure - gen_hdr = create_ack_2_struct(password); - CHECK_FOR_NULL_HDR(gen_hdr); + if (!store_pwd((char*)hdr_pwd_request->nickname, hdr_pwd_request->expiration1, hdr_pwd_request->expiration2, password)) + return 0; - // Send password ack structure - SENDTO(global_accept.socket_desc, socket_addr, gen_hdr); + // Create password ack structure + gen_hdr = create_ack_2_struct(password); + CHECK_FOR_NULL_HDR(gen_hdr); - free(gen_hdr); + // Send password ack structure + SENDTO(global_accept.socket_desc, socket_addr, gen_hdr); + pisa_hitlist_destroy(allowed_hosts); + free(gen_hdr); - return 1; + + return 1; } @@ -202,203 +186,110 @@ int store_pwd(char *nickname, long int expr1, long int expr2, char *password) { - assert(nickname != NULL); - assert(password != NULL); - - // Write down password - config_t cfg; - config_setting_t *root; - config_setting_t *allowed_passwords; - config_setting_t *new_pwd_grp, *new_nick, *new_pwd, *new_expire1, *new_expire2; - char expiration1[LENGTH_TIMEOUT], expiration2[LENGTH_TIMEOUT]; - - struct tm *ts; - time_t time_exp1, time_exp2; - - /** @todo Generate password rather than write statically. **/ - strcpy(password, "aachen2"); - - config_init(&cfg); - if (!config_read_file(&cfg, FILE_AUTHORIZED_HOSTS)) - { - DEBUG("Could not read file \'%s\'.", FILE_AUTHORIZED_HOSTS); - return 0; - } - - root = config_root_setting(&cfg); - - allowed_passwords = config_lookup(&cfg, "allowed_passwords"); - if (!allowed_passwords) - { - DEBUG_HIGH("List allowed_passwords did not previously exist. Creating..."); - allowed_passwords = config_setting_add(root, "allowed_passwords", CONFIG_TYPE_LIST); - } - - time(&time_exp1); - time(&time_exp2); + assert(nickname != NULL); + assert(password != NULL); - time_exp1 += expr1; - time_exp2 += expr2; + // Write down password + config_setting_t *allowed_passwords; + config_setting_t *new_pwd_grp, *new_nick, *new_pwd, *new_expire1, *new_expire2; + char expiration1[LENGTH_TIMEOUT], expiration2[LENGTH_TIMEOUT]; - ts = localtime(&time_exp1); - strftime(expiration1, sizeof(expiration1), EXPIRATION_DATE_FORMAT, ts); - ts = localtime(&time_exp2); - strftime(expiration2, sizeof(expiration2), EXPIRATION_DATE_FORMAT, ts); - - // Add a new group - new_pwd_grp = config_setting_add(allowed_passwords, NULL, CONFIG_TYPE_GROUP); - - // Add the nickname - new_nick = config_setting_add(new_pwd_grp, "nickname", CONFIG_TYPE_STRING); - if (strlen(nickname) == 0) - { - DEBUG_HIGH("Reading nickname from config file."); + struct tm *ts; + time_t time_exp1, time_exp2; - // Read config file - int unknown_user_count_int; - char unknown_user_count_string[5]; - - config_t cfg; - config_setting_t *root; - config_setting_t *unknown_user_count_setting; - config_init(&cfg); - - if (!config_read_file(&cfg, FILE_SERVER_CONFIG)) - { - DEBUG("Could not read file \'%s\'.", FILE_SERVER_CONFIG); - return 0; - } - - root = config_root_setting(&cfg); - unknown_user_count_setting = config_lookup(&cfg, "pwd_request_settings.unknown_user_count"); - if (!unknown_user_count_setting) - { - DEBUG("Error reading unknown user count setting from file %s.", FILE_SERVER_CONFIG); - return 0; - } - - // Build the default nickname - unknown_user_count_int = config_setting_get_int(unknown_user_count_setting); - strcpy(nickname, "unknown"); - itoa(unknown_user_count_int, unknown_user_count_string); - strcat(nickname, unknown_user_count_string); - - // Update the unknown user count - unknown_user_count_int++; - if (config_setting_set_int(unknown_user_count_setting, unknown_user_count_int) != CONFIG_TRUE) - { - DEBUG("Error setting unknown user count."); - return 0; - } - - config_setting_set_string(new_nick, nickname); - - if (config_write_file(&cfg, FILE_SERVER_CONFIG) == CONFIG_FALSE) - { - DEBUG("Error writing to file %s.", FILE_SERVER_CONFIG); - return 0; - } - config_destroy(&cfg); - } - else - config_setting_set_string(new_nick, nickname); + /** @todo Generate password rather than write statically. **/ + strcpy(password, "aachen2"); - // Add the password - new_pwd = config_setting_add(new_pwd_grp, "password", CONFIG_TYPE_STRING); - config_setting_set_string(new_pwd, password); - // Add the password expiration date - new_expire1 = config_setting_add(new_pwd_grp, "pwd_expires", CONFIG_TYPE_STRING); - config_setting_set_string(new_expire1, expiration1); - // Add the access expiration date - new_expire2 = config_setting_add(new_pwd_grp, "access_expires", CONFIG_TYPE_STRING); - config_setting_set_string(new_expire2, expiration2); - - DEBUG_HIGH("Password information written."); - DEBUG_HIGH("\tNickname: %s", nickname); - DEBUG_HIGH("\tPassword: %s", password); - DEBUG_HIGH("\tExpiration 1: %s", expiration1); - DEBUG_HIGH("\tExpiration 2: %s", expiration2); + allowed_passwords = check_list("allowed_passwords"); - config_write_file(&cfg, FILE_AUTHORIZED_HOSTS); - config_destroy(&cfg); + time(&time_exp1); + time(&time_exp2); + time_exp1 += expr1; + time_exp2 += expr2; - return 1; -} + ts = localtime(&time_exp1); + strftime(expiration1, sizeof(expiration1), EXPIRATION_DATE_FORMAT, ts); + ts = localtime(&time_exp2); + strftime(expiration2, sizeof(expiration2), EXPIRATION_DATE_FORMAT, ts); + // Add a new group + new_pwd_grp = config_setting_add(allowed_passwords, NULL, CONFIG_TYPE_GROUP); + // Add the nickname + new_nick = config_setting_add(new_pwd_grp, "nickname", CONFIG_TYPE_STRING); + if (strlen(nickname) == 0) + { + DEBUG_HIGH("Reading nickname from config file."); -/** Determines if the HIT is written in FILE_AUTHORIZED_HOSTS. - * - * @param hit HIT to be tested. - * - * @return 1 if found; 0 otherwise - */ -int is_allowed_hit(char *hit) -{ - assert(hit != NULL); + // Read config file + int unknown_user_count_int; + char unknown_user_count_string[5]; config_t cfg; config_setting_t *root; - config_setting_t *allowed_hosts; - + config_setting_t *unknown_user_count_setting; config_init(&cfg); - if (!config_read_file(&cfg, FILE_AUTHORIZED_HOSTS)) + + if (!config_read_file(&cfg, FILE_SERVER_CONFIG)) { - DEBUG("Could not read file \'%s\'.", FILE_AUTHORIZED_HOSTS); - return 0; + DEBUG("Could not read file \'%s\'.", FILE_SERVER_CONFIG); + return 0; } root = config_root_setting(&cfg); + unknown_user_count_setting = config_lookup(&cfg, "pwd_request_settings.unknown_user_count"); + if (!unknown_user_count_setting) + { + DEBUG("Error reading unknown user count setting from file %s.", FILE_SERVER_CONFIG); + return 0; + } - allowed_hosts = config_lookup(&cfg, "allowed_hosts"); - if (!allowed_hosts) + // Build the default nickname + unknown_user_count_int = config_setting_get_int(unknown_user_count_setting); + strcpy(nickname, "unknown"); + itoa(unknown_user_count_int, unknown_user_count_string); + strcat(nickname, unknown_user_count_string); + + // Update the unknown user count + unknown_user_count_int++; + if (config_setting_set_int(unknown_user_count_setting, unknown_user_count_int) != CONFIG_TRUE) { - DEBUG_HIGH("No HITs have been stored."); - return 0; + DEBUG("Error setting unknown user count."); + return 0; } - { // Iterate over the list - const char* hit_text = NULL; - int length = config_setting_length(allowed_hosts); - int i; - - for (i = 0; i < length; i++) - { - config_setting_t *group_element = NULL; - group_element = config_setting_get_elem(allowed_hosts, i); - - if (!group_element) - { - DEBUG("Error while parsing config file \'%s\'. Exiting function.", FILE_AUTHORIZED_HOSTS); - return 0; - } - - config_setting_t *this_hit = NULL; - this_hit = config_setting_get_member(group_element, "hit"); - - if (!this_hit) - { - DEBUG("Error extracting HIT from group %d in file %s. Exiting function.", i, FILE_AUTHORIZED_HOSTS); - return 0; - } - - hit_text = NULL; - hit_text = config_setting_get_string(this_hit); - - if (hit_text != NULL && strlen(hit_text)>0) - DEBUG("HIT = %s", hit_text); - else - DEBUG("Error extracting HIT."); - - if (identical_hits((char*)hit_text, hit) == 1) - return 1; - } + config_setting_set_string(new_nick, nickname); + + if (config_write_file(&cfg, FILE_SERVER_CONFIG) == CONFIG_FALSE) + { + DEBUG("Error writing to file %s.", FILE_SERVER_CONFIG); + return 0; } + config_destroy(&cfg); + } + else + config_setting_set_string(new_nick, nickname); + + // Add the password + new_pwd = config_setting_add(new_pwd_grp, "password", CONFIG_TYPE_STRING); + config_setting_set_string(new_pwd, password); + // Add the password expiration date + new_expire1 = config_setting_add(new_pwd_grp, "pwd_expires", CONFIG_TYPE_STRING); + config_setting_set_string(new_expire1, expiration1); + // Add the access expiration date + new_expire2 = config_setting_add(new_pwd_grp, "access_expires", CONFIG_TYPE_STRING); + config_setting_set_string(new_expire2, expiration2); + + DEBUG_HIGH("Password information written."); + DEBUG_HIGH("\tNickname: %s", nickname); + DEBUG_HIGH("\tPassword: %s", password); + DEBUG_HIGH("\tExpiration 1: %s", expiration1); + DEBUG_HIGH("\tExpiration 2: %s", expiration2); + pisa_cfg_write_authorized_hosts_file(); - DEBUG_LOW("HIT \'%s\' not allowed. Ignoring request.", hit); - return 0; + return 1; } Modified: trunk/pairing/packet_handler_accept.h ============================================================================== --- trunk/pairing/packet_handler_accept.h Tue Aug 18 15:21:27 2009 (r823) +++ trunk/pairing/packet_handler_accept.h Wed Aug 19 11:54:30 2009 (r824) @@ -7,6 +7,7 @@ * @file packet_handler_accept.h * @brief Header file of post-accept process functions for packet handlers * @author Kate Harrison <harriska@xxxxxxxxxxxxx> + * @author Jan Marten <jan.marten@xxxxxxxxxxxxxx> * @date Sep. 2008 */ @@ -28,6 +29,5 @@ int check_password(char *password); int handle_packet_pwd_request(struct sockaddr_in6 *socket_addr, header_pwd_request *hdr_pwd_request); int store_pwd(char *nickname, long int expr1, long int expr2, char *password); -int is_allowed_hit(char *hit); #endif /* PISA_PAIR_PACKET_HANDLER_ACCEPT_H */