[pisa-src] r1836 - in trunk: Makefile.am pairing/packet_handler.c pairing/packet_handler_accept.c pairing/packet_handler_accept.h

  • From: Diego Biurrun <diego@xxxxxxxxxx>
  • To: pisa-src@xxxxxxxxxxxxx
  • Date: Thu, 26 Nov 2009 18:16:36 +0100

Author: biurrun
Date: Thu Nov 26 18:16:32 2009
New Revision: 1836

Log:
Move handle_packet_password / handle_packet_pwd_request (and dependencies)
to the only place they are used and mark them as static.

Deleted:
   trunk/pairing/packet_handler_accept.c
   trunk/pairing/packet_handler_accept.h
Modified:
   trunk/Makefile.am
   trunk/pairing/packet_handler.c

Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am   Thu Nov 26 18:03:17 2009        (r1835)
+++ trunk/Makefile.am   Thu Nov 26 18:16:32 2009        (r1836)
@@ -80,8 +80,7 @@
                              pairing/packet_handler.c
 
 pairing_accept_SOURCES     = $(pairing_ACCEPT_SEND_SRCS)     \
-                             pairing/accept.c                \
-                             pairing/packet_handler_accept.c
+                             pairing/accept.c
 
 pairing_send_SOURCES       = $(pairing_ACCEPT_SEND_SRCS)   \
                              pairing/send.c

Modified: trunk/pairing/packet_handler.c
==============================================================================
--- trunk/pairing/packet_handler.c      Thu Nov 26 18:03:17 2009        (r1835)
+++ trunk/pairing/packet_handler.c      Thu Nov 26 18:16:32 2009        (r1836)
@@ -11,13 +11,466 @@
  */
 
 #include <libconfig.h>
+#include <openssl/sha.h>
 #include <stdio.h>
 #include <string.h>
 #include <netinet/in.h>
+#include "libpisa/hitlist.h"
 #include "common.h"
+#include "common_headers.h"
+#include "libconfig_wrapper.h"
 #include "packet_handler.h"
 
 
+/** Default password file is set statically. **/
+#define FILE_PWD "sha.txt"
+
+#define ERROR_INVALID_PWD   0
+#define ERROR_NOT_CONNECTED 1
+
+
+/** Creates an error structure and fills it with the information given.
+ *
+ *  @param error_type Error type (use macros ERROR_*)
+ *  @param error_string Pointer to string containing an error message.
+ *
+ *  @return A pointer to the header_general structure. Returns NULL on error.
+ */
+static header_general* create_error_struct(int error_type,
+                                           const char *error_string)
+{
+       if (error_string == NULL)
+       {
+               DEBUG("No error string given. Error structure was not 
created.");
+               return NULL;
+       }
+
+       header_general *gen_hdr = malloc(sizeof(header_general));
+       gen_hdr->msg_type = MSG_ERROR;
+       gen_hdr->msg.header_error.error_type = error_type;
+       strncpy((char*)&((gen_hdr->msg.header_error).error_string), 
error_string, LENGTH_ERROR_STRING);
+
+       DEBUG_HIGH(LINE_BREAK);
+       DEBUG_HIGH("General header created.");
+       DEBUG_HIGH("\tMessage type: %d", gen_hdr->msg_type);
+       DEBUG_HIGH("Error structure created:");
+       DEBUG_HIGH("\tError type: %d", gen_hdr->msg.header_error.error_type);
+       DEBUG_HIGH("\tError string: %s", 
(gen_hdr->msg.header_error).error_string);
+       DEBUG_HIGH(LINE_BREAK);
+
+       return gen_hdr;
+}
+
+
+/** Creates a header_general structure which holds a header_ack_1 structure 
and fills both.
+ *
+ *  @return A pointer to the header_general structure. Returns NULL on error.
+ */
+static header_general* create_ack_1_struct(void)
+{
+        config_t cfg;
+        const char *nickname, *ipv4_addr, *ipv6_addr;
+       int success;
+
+        header_general *gen_hdr = malloc(sizeof(header_general));
+        gen_hdr->msg_type = MSG_ACK_1;
+
+        // Read config file
+        config_init(&cfg);
+        if (!config_read_file(&cfg, FILE_SERVER_CONFIG))
+        {
+                DEBUG("Error reading %s on line %d: %s\n", FILE_SERVER_CONFIG, 
cfg.error_line, cfg.error_text);
+                return NULL;
+        }
+
+        DEBUG_HIGH(LINE_BREAK);
+        DEBUG_HIGH("General header created.");
+        DEBUG_HIGH("\tMessage type: %d", gen_hdr->msg_type);
+        DEBUG_HIGH("ack_1 structure created:");
+
+
+        // Look up nickname
+        success = config_lookup_string(&cfg, "server_settings.nickname", 
&nickname);
+        if (success != CONFIG_TRUE || !nickname)
+        {       // If the setting doesn't exist, set the string to be empty
+                *((gen_hdr->msg.header_ack_1).nickname) = 0;
+                DEBUG_HIGH("\nNickname not found.");
+        }
+        else    // ... write the contents into the structure
+                strncpy((char*)&((gen_hdr->msg.header_ack_1).nickname), 
nickname, LENGTH_NICKNAME);
+        DEBUG_HIGH("\tNickname: \'%s\'", 
((gen_hdr->msg.header_ack_1).nickname));
+
+
+        // Look up the IPv4 address
+        success = config_lookup_string(&cfg, "server_settings.ipv4_addr", 
&ipv4_addr);
+        if (success != CONFIG_TRUE || !ipv4_addr)
+        {       // If the setting doesn't exist, set the string to be empty
+                *((gen_hdr->msg.header_ack_1).ipv4_addr) = 0;
+                DEBUG_HIGH("\tIPv4 address not found!");
+        }
+        else    // ... write the contents into the structure
+                strncpy((char*)&((gen_hdr->msg.header_ack_1).ipv4_addr), 
ipv4_addr, INET_ADDRSTRLEN+1);
+        DEBUG_HIGH("\tIPv4 address: \'%s\'", 
(gen_hdr->msg.header_ack_1).ipv4_addr);
+
+
+        // Look up the IPv6 address
+        success = config_lookup_string(&cfg, "server_settings.ipv6_addr", 
&ipv6_addr);
+        if (success != CONFIG_TRUE || !ipv6_addr)
+        {       // If the setting doesn't exist, set the string to be empty
+                *((gen_hdr->msg.header_ack_1).ipv6_addr) = 0;
+                DEBUG_HIGH("\tIPv6 address not found!");
+        }
+        else    // ... write the contents into the structure
+                strncpy((char*)&((gen_hdr->msg.header_ack_1).ipv6_addr), 
ipv6_addr, INET6_ADDRSTRLEN+1);
+        DEBUG_HIGH("\tIPv6 address: \'%s\'", 
(gen_hdr->msg.header_ack_1).ipv6_addr);
+
+        config_destroy(&cfg);
+
+        DEBUG_HIGH(LINE_BREAK);
+
+        return gen_hdr;
+}
+
+
+/** Creates a header_general structure which holds a header_ack_2 structure 
and fills both.
+ *
+ *  @return A pointer to the header_general structure. Returns NULL on error.
+ */
+static header_general* create_ack_2_struct(char *password)
+{
+        assert(password != NULL);
+
+        header_general *gen_hdr = malloc(sizeof(header_general));
+        gen_hdr->msg_type = MSG_ACK_2;
+
+        strncpy((char*)&((gen_hdr->msg.header_ack_2).password), password, 
LENGTH_PASSWORD);
+
+        DEBUG_HIGH(LINE_BREAK);
+        DEBUG_HIGH("General header created.");
+        DEBUG_HIGH("\tMessage type: %d", gen_hdr->msg_type);
+        DEBUG_HIGH("Password structure created:");
+        DEBUG_HIGH("\tPassword: \'%s\'", (gen_hdr->msg.header_ack_2).password);
+        DEBUG_HIGH(LINE_BREAK);
+
+        return gen_hdr;
+}
+
+
+/** This function authenticates the password.
+ *
+ *  @todo Read from config file instead of sha.txt?
+ *
+ *  @param password A pointer to string containing the received password.
+ *  @return 1 if the password matches, 0 if the password does not match
+ */
+static int check_password(char *password)
+{
+        FILE *file;
+        char file_contents[2*SHA_DIGEST_LENGTH+1];
+        int result;
+        char pwd_hash_hex[2*SHA_DIGEST_LENGTH+1];
+
+        assert(password != NULL);
+        DEBUG_MED("Checking password: %s", password);
+
+        // Open file
+        if ((file = fopen(FILE_PWD, "r")) == NULL)
+        {
+                DEBUG("Cannot open password file.\n");
+                return 0;
+        }
+
+        // Read line
+        if (!fgets(file_contents, 2*SHA_DIGEST_LENGTH+1, file))
+               return 0;
+        file_contents[2*SHA_DIGEST_LENGTH] = 0; // Null-terminate the line
+        DEBUG_MED("File contents:\t\'%s\'", file_contents);
+
+        get_sha(password, pwd_hash_hex);        // Get the SHA1 hash of 
/password/
+        DEBUG_MED("Hash is:\t\t\'%s\'", pwd_hash_hex);
+        result = strcmp(pwd_hash_hex, file_contents);   // Compare the 
password with the file contents
+
+        // Close file
+        if (fclose(file))
+                DEBUG("File close error.\n");
+
+        return (result == 0) ? 1 : 0 ;
+
+}
+
+
+/** This function handles a password packet sent from the user to the relay.
+ *
+ *  @param socket_addr Pointer to sockaddr_in6 structure connected to peer.
+ *  @param hdr_pwd Pointer to the header_password structure to be handled.
+ *
+ *  @return The result of the password authentication.
+ */
+static 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...");
+
+    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.");
+
+    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))
+        {
+            return 0;
+        }
+
+        inet_ntop(AF_INET6, &socket_addr->sin6_addr, hit, sizeof(hit));
+        write_config(hit, buf_expiration, CONFIG_TYPE_HIT);
+    }
+
+    return 1;
+}
+
+
+/* Stolen from http://en.wikipedia.org/wiki/Itoa */
+/** Convert an integer to a string
+ *
+ *  @param n Original integer
+ *  @param s String to hold result
+*/
+static void itoa(int n, char s[])
+{
+       int i, sign;
+
+       if ((sign = n) < 0)  /* record sign */
+               n = -n;          /* make n positive */
+       i = 0;
+       do
+       {       /* generate digits in reverse order */
+               s[i++] = n % 10 + '0';   /* get next digit */
+       } while ((n /= 10) > 0);     /* delete it */
+
+       if (sign < 0)
+               s[i++] = '-';
+
+       s[i] = '\0';
+
+// reverse(s); // Orignal; inserted code below
+
+       {
+               int c, j;
+               for (i = 0, j = strlen(s)-1; i<j; i++, j--)
+               {
+                       c = s[i];
+                       s[i] = s[j];
+                       s[j] = c;
+               }
+       }
+
+}
+
+
+/** Creates a new password with the associated information and writes it all
+ *      in FILE_AUTHORIZED_HOSTS.
+ *
+ *  @param nickname Pointer to the nickname for this relay. Leave blank (not 
null) to autogenerate one.
+ *  @param expr1 Long int representing the length of time for which the 
password is valid in seconds.
+ *  @param expr2 Long int representing the length of time for which access 
will be allowed in seconds.
+ *  @param password Pointer to a string to contain the new (generated) 
password.
+ *
+ *  @return 1 if everything goes well; 0 otherwise
+ */
+static int store_pwd(char *nickname, long int expr1, long int expr2, char 
*password)
+{
+
+    assert(nickname != NULL);
+    assert(password != NULL);
+
+    // 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];
+
+    struct tm *ts;
+    time_t time_exp1, time_exp2;
+
+    /** @todo Generate password rather than write statically. **/
+    strcpy(password, "aachen2");
+
+    allowed_passwords = check_list("allowed_passwords");
+
+    time(&time_exp1);
+    time(&time_exp2);
+
+    time_exp1 += expr1;
+    time_exp2 += expr2;
+
+    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.");
+
+        // 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);
+
+    // 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();
+
+
+    return 1;
+}
+
+
+/** Handles a password request packet.
+ *
+ *  @param socket_addr Pointer to sockaddr_in6 structure connected to peer.
+ *  @param hdr_pwd_request Pointer to the header_pwd_request structure.
+ *
+ *  @return 1 if password generated; 0 otherwise
+ */
+static int handle_packet_pwd_request(struct sockaddr_in6 *socket_addr,
+                                     header_pwd_request *hdr_pwd_request)
+{
+    pisa_hitlist *allowed_hosts;
+    pisa_hitlist_entry *con;
+
+    assert(socket_addr != NULL);
+    assert(hdr_pwd_request != NULL);
+
+    header_general *gen_hdr;
+    char password[LENGTH_PASSWORD];
+
+    // 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);
+
+        // Transmit message
+        SENDTO(global_accept.socket_desc, socket_addr, gen_hdr);
+
+        free(gen_hdr);
+
+        return 0;
+    }
+
+    if (!store_pwd((char*)hdr_pwd_request->nickname, 
hdr_pwd_request->expiration1, hdr_pwd_request->expiration2, password))
+        return 0;
+
+    // Create password ack structure
+    gen_hdr = create_ack_2_struct(password);
+    CHECK_FOR_NULL_HDR(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;
+}
+
 /** Stores the contact information of a relay in FILE_KNOWN_RELAYS.
  *
  *  @param nickname Pointer to the string containing the suggested nickname of 
the relay.

Other related posts:

  • » [pisa-src] r1836 - in trunk: Makefile.am pairing/packet_handler.c pairing/packet_handler_accept.c pairing/packet_handler_accept.h - Diego Biurrun