diff options
author | Luke Bratch <luke@bratch.co.uk> | 2019-05-12 20:56:55 +0100 |
---|---|---|
committer | Luke Bratch <luke@bratch.co.uk> | 2019-05-12 20:56:55 +0100 |
commit | e18e670f43f0e7b126f209c040126aa02511fa32 (patch) | |
tree | 798e297304c0ce051847359ebf32af63503b67c8 | |
parent | 34836ab2c9124e17d80bd8e8a1601398297391a8 (diff) |
Completely rewrite configuration file reading to remove lots of duplicated code and to simplify things. Alter everything that called the old functions.
-rw-r--r-- | blabouncer.c | 46 | ||||
-rw-r--r-- | config.c | 259 | ||||
-rw-r--r-- | config.h | 17 | ||||
-rw-r--r-- | functions.c | 4 |
4 files changed, 130 insertions, 196 deletions
diff --git a/blabouncer.c b/blabouncer.c index d96ec09..5da18e0 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -70,6 +70,8 @@ #define MAXREALNAMELEN 128 // Randomly picked (TODO - is there an actual maximum real name length?) #define MAXPORTLEN 6 // Up to 65535, so 5 characters + 1 for null +#define CONFFILE "blabouncer.conf" + struct channel { char name[MAXCHANLENGTH]; char topic[MAXDATASIZE]; // TODO - Is there a particular maximum topic length? @@ -91,7 +93,6 @@ struct ircdstrings { char nickuserhost[MAXDATASIZE]; // TODO - Make sure this changes when nick changes, if that's meant to happen. char ircnick[MAXNICKLENGTH]; // TODO - Make sure this changes when nick changes char ircusername[MAXUSERNAMELEN]; - char ircrealname[MAXREALNAMELEN]; char currentmsg[MAXDATASIZE]; // Holding area for the current server-received IRC message being processed in case it needs building across multiple reads (i.e. a truncated/split message) }; @@ -99,6 +100,9 @@ struct ircdstrings { struct settings { int replayseconds; char clientport[MAXPORTLEN]; + char ircnick[MAXNICKLENGTH]; // In both settings and ircdstrings as settings is from our file whereas server may change ircdstrings copy + char ircusername[MAXUSERNAMELEN]; // (Is this also true for the username? Can the server change that?) + char ircrealname[MAXREALNAMELEN]; }; int debugmode = 0; @@ -665,7 +669,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc case SOURCE_CLIENT: // If message(s) were from a real IRC client // PASS received? User is trying to log in, check their password. if (strncmp(tokens[0], "PASS", strlen(tokens[0])) == 0) { - if (checkpassword(tokens[1])) { + if (checkpassword(tokens[1], CONFFILE)) { printf("Password accepted! Setting fd %d to authenticated.\n", sourcefd); // Find the client in the clients array and set them as authenticated for (int i = 0; i < MAXCLIENTS; i++) { @@ -1049,11 +1053,11 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { ircdstrings.nickuserhost[0] = '\0'; ircdstrings.ircnick[0] = '\0'; ircdstrings.ircusername[0] = '\0'; - ircdstrings.ircrealname[0] = '\0'; ircdstrings.currentmsg[0] = '\0'; - // Read required things from configuration file - readnames(ircdstrings.ircnick, ircdstrings.ircusername, ircdstrings.ircrealname); + // Populate nick and username from our configuration file for now, real IRCd may change them later (TODO - Is this true of username?) + strcpy(ircdstrings.ircnick, settings->ircnick); + strcpy(ircdstrings.ircusername, settings->ircusername); // Send our NICK snprintf(outgoingmsg, MAXDATASIZE, "NICK %s", ircdstrings.ircnick); // TODO - Check for success (with return code) @@ -1061,7 +1065,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg), 0, arr_clients, arr_authed); // Send our USER - snprintf(outgoingmsg, MAXDATASIZE, "USER %s 8 * : %s", ircdstrings.ircusername, ircdstrings.ircrealname); // TODO - Check for success (with return code) + snprintf(outgoingmsg, MAXDATASIZE, "USER %s 8 * : %s", ircdstrings.ircusername, settings->ircrealname); // TODO - Check for success (with return code) // TODO - Send a more intelligent/correct USER string // sourcefd = 0 as this is a trusted message sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg), 0, arr_clients, arr_authed); @@ -1278,8 +1282,34 @@ int main(int argc, char *argv[]) { // Structure of our various settings which are to either be read from the configuration file or set at runtime struct settings settings; - settings.replayseconds = confreplayseconds(); - confclientport(settings.clientport); + + // Populate said settings + + // How many seconds of replay log should automatically be replayed - TODO - Can we do error checking on this? + settings.replayseconds = getconfint("replayseconds", CONFFILE); + // What port should the bouncer listen on + if (!getconfstr("clientport", CONFFILE, settings.clientport)) { + printf("main(): error getting clientport from configuration file.\n"); + exit(1); + } + + // What is the configured nick? + if (!getconfstr("nick", CONFFILE, settings.ircnick)) { + printf("main(): error getting nick from configuration file.\n"); + exit(1); + } + + // What is the configured username? + if (!getconfstr("username", CONFFILE, settings.ircusername)) { + printf("main(): error getting username from configuration file.\n"); + exit(1); + } + + // What is the configured real name? + if (!getconfstr("realname", CONFFILE, settings.ircrealname)) { + printf("main(): error getting real name from configuration file.\n"); + exit(1); + } // TODO: see if any of this can be shared (i.e. 1. avoid code duplication, and 2. see if variables can be shared between client/server sockets) @@ -1,227 +1,128 @@ #include "config.h" -// TODO - Multiple functions here (at least readnames(), replayseconds() and checkpassword()) have the file opening code, rewrite. +// Sets 'dest' to the value of the configuration option with name +// 'confname' from configuration file 'filename'. +// Returns 1 for success or 0 for error/failure. +int getconfstr(char *confname, char *filename, char* dest) { + FILE *fp; + char *ret; + char str[MAXCHAR]; -// TODO - Can isconf() and getconf() just be merged into one function? + // Set strings to zero-length to begin + dest[0] = '\0'; -// Check to see if a line is the configuration option specified by -// checking to see if str starts with conf followed by a space, a tab, -// or an equals sign. -// Returns the length of the name of the requested option if found, or -// zero if not. -long int isconf(char *str, char *conf) { - char *ret; - char substr[MAXCHAR]; - long int len = strlen(conf); + // Length of requested configuration option name + long int namelen = strlen(confname); - // Ensure the next character is an equals sign, a space, or a tab - if (str[len] != '=' && str[len] != ' ' && str[len] != ' ') { - return 0; + fp = fopen(filename, "r"); + + if (fp == NULL) { + printf("error: could not open configuration file '%s'.\n", filename); + exit(1); } + // Loop through the whole file, looking for the requested configuration option + while (fgets(str, MAXCHAR, fp) != NULL) { + char substr[MAXCHAR]; - strncpy(substr, str, len); - substr[len] = '\0'; + // Check if the next character after the length of the requested option + // name is an equals sign, a space, or a tab + if (str[namelen] != '=' && str[namelen] != ' ' && str[namelen] != ' ') { + // If it isn't this can't have been our option + continue; + } + // Copy the number of characters that the requested option name is long + // to a temporary string + strncpy(substr, str, namelen); + substr[namelen] = '\0'; - if (!(ret = strstr(substr, conf)) == 0) { - return len; + // If the resulting temporary string contains the requested option name, + // we have found our configuration option and it is in the current 'str' + if (!(ret = strstr(substr, confname)) == 0) { + break; + } } - return 0; -} + // If we got here, then either we found the configuration option or we ran out of file + + // If str is NULL then we ran out of file + if (ret == NULL) { + printf("Error reading configuration option '%s', did not find it in configuration file '%s'.\n", confname, filename); + return 0; + } -// Extracts the value of a configuration option from a string. Expects -// to receive the string and the number of characters long that the -// configuration option name is. -void getconf(char *str, long int start) { - long int len = strlen(str); long int pos; - char conf[MAXCHAR]; + char conf[MAXCHAR]; // Temporary string to build configuration value in - for (long int i = start; i < len; i++) { + // Starting from the end of the option name, find the position of the start of the configuration value + // (including its double quotes) by skipping over everything that isn't an equals sign, a space, or a tab + for (size_t i = namelen; i < strlen(str); i++) { if (str[i] == '=' || str[i] == ' ' || str[i] == ' ') { continue; } else { + // Record current/final position in string pos = i; break; } } - strncpy(conf, str + pos, len - pos - 1); // Copy remainder to new string and lop off the newline - conf[len - pos - 1] = '\0'; // Null terminate + strncpy(conf, str + pos, strlen(str) - pos - 1); // Copy remainder to new string and lop off the newline + conf[strlen(str) - pos - 1] = '\0'; // Null terminate // Check for start and end quotes if (conf[0] != '"' || conf[strlen(conf) - 1] != '"') { - printf("Error reading configuration option, not enclosed in double quotes!\n"); + printf("Error reading configuration option '%s', not enclosed in double quotes in configuration file '%s'!\n", confname, filename); exit(1); } - strncpy(str, conf + 1, strlen(conf) - 2); // Copy result back to original string without quotes - str[strlen(conf) - 2] = '\0'; // Null terminate -} - -int readnames(char *nick, char *username, char *realname) { - FILE *fp; - char str[MAXCHAR]; - char* filename = "blabouncer.conf"; + strncpy(dest, conf + 1, strlen(conf) - 2); // Copy result to destination string without quotes + dest[strlen(conf) - 2] = '\0'; // Null terminate - // Set all strings to zero-length to begin - nick[0] = '\0'; - username[0] = '\0'; - realname[0] = '\0'; - - fp = fopen(filename, "r"); - - if (fp == NULL) { - printf("error: could not open configuration file '%s'.\n", filename); - exit(1); - } - - while (fgets(str, MAXCHAR, fp) != NULL) { - long int len; - if ((len = isconf(str, "nick"))) { - getconf(str, len); - strncpy(nick, str, strlen(str)); - nick[strlen(str)] = '\0'; - printf("Nick is: '%s', length '%ld'.\n", nick, strlen(nick)); - } else if ((len = isconf(str, "username"))) { - getconf(str, len); - strncpy(username, str, strlen(str)); - username[strlen(str)] = '\0'; - printf("Username is: '%s', length '%ld'.\n", username, strlen(username)); - } else if ((len = isconf(str, "realname"))) { - getconf(str, len); - strncpy(realname, str, strlen(str)); - realname[strlen(str)] = '\0'; - printf("Real name is: '%s', length '%ld'.\n", realname, strlen(realname)); - } - } - - // Ensure we have everything required - if (!strlen(nick) || !strlen(username) || !strlen(realname)) { - printf("Failed to read nick and/or username and/or real name from configuration file.\n"); - exit(1); - } + printf("getconfstr(): returning '%s'.\n", dest); + // Close fine and return success fclose(fp); return 1; } -// Return the replayseconds configuration option -// (How many seconds of replay should be sent to connecting clients) -int confreplayseconds() { - FILE *fp; - char str[MAXCHAR]; - char* filename = "blabouncer.conf"; - - char secondsstr[MAXCHAR]; - int seconds; - - fp = fopen(filename, "r"); - - if (fp == NULL) { - printf("error: could not open configuration file '%s'.\n", filename); +// Returns the value of the configuration option with name +// 'confname' from configuration file 'filename'. +int getconfint(char *confname, char *filename) { + char result[MAXCHAR]; + if (!getconfstr(confname, filename, result)) { + printf("getconfint(): error getting configuration option '%s' from configuration file '%s'.\n", confname, filename); + // TODO - Do something useful here instead of exiting exit(1); } - while (fgets(str, MAXCHAR, fp) != NULL) { - long int len; - if ((len = isconf(str, "replayseconds"))) { - getconf(str, len); - strncpy(secondsstr, str, strlen(str)); - secondsstr[strlen(str)] = '\0'; - printf("secondsstr is: '%s', length '%ld'.\n", secondsstr, strlen(secondsstr)); - seconds = strtol(secondsstr, NULL, 10); // Convert resulting string to an integer, base 10 - printf("seconds is: '%d'.\n", seconds); - } - } - - fclose(fp); - return seconds; + return strtol(result, NULL, 10); // Convert resulting string to an integer, base 10 } // Check the password provided in the string 'str' against what is in -// the config file. +// the configuration file 'filename'. // Return 0 for password mismatch, or 1 for password match. -int checkpassword(char *password) { - FILE *fp; - char str[MAXCHAR]; - char* filename = "blabouncer.conf"; - - fp = fopen(filename, "r"); - - if (fp == NULL) { - printf("error: could not open configuration file '%s'.\n", filename); - exit(1); - } - - while (fgets(str, MAXCHAR, fp) != NULL) { - long int len; - if ((len = isconf(str, "password"))) { - getconf(str, len); - printf("confpassword is: '%s', length '%ld'.\n", str, strlen(str)); - // Ensure password are the same length - if (strlen(str) != strlen(password)) { - printf("Password length mismatch!\n"); - fclose(fp); - return 0; - } - // Ensure passwords match - if (strncmp(str, password, strlen(password)) == 0) { - printf("confpassword matches password.\n"); - fclose(fp); - return 1; - } else { - printf("confpassword does NOT match password!\n"); - fclose(fp); - return 0; - } - } - } - - fclose(fp); - printf("No password read from configuration file, quitting.\n"); - exit(1); -} +int checkpassword(char *password, char *filename) { + char confpassword[MAXCHAR]; -int confclientport(char *clientport) { - FILE *fp; - char str[MAXCHAR]; - char* filename = "blabouncer.conf"; - - // Set all strings to zero-length to begin - clientport[0] = '\0'; - - fp = fopen(filename, "r"); - - if (fp == NULL) { - printf("error: could not open configuration file '%s'.\n", filename); - exit(1); - } - - while (fgets(str, MAXCHAR, fp) != NULL) { - long int len; - if ((len = isconf(str, "clientport"))) { - getconf(str, len); - strncpy(clientport, str, strlen(str)); - clientport[strlen(str)] = '\0'; - printf("clientport is: '%s', length '%ld'.\n", clientport, strlen(clientport)); - } + if (!getconfstr("password", filename, confpassword)) { + printf("checkpassword(): error getting configuration option 'password' from configuration file '%s'.\n", filename); + return 0; } - // Ensure we have everything required - if (!strlen(clientport)) { - printf("Failed to read clientport from configuration file.\n"); - exit(1); + // Ensure passwords are the same length + if (strlen(password) != strlen(confpassword)) { + printf("Password length mismatch!\n"); + return 0; } - - int portint = strtol(clientport, NULL, 10); // Convert resulting string to an integer, base 10 - // Ensure port is valid - if (portint < 1 || portint > 65535) { - printf("Invalid clientport value in configuration file.\n"); - exit(1); + // Ensure passwords match + if (strncmp(password, confpassword, strlen(password)) == 0) { + printf("confpassword matches password.\n"); + return 1; + } else { + printf("confpassword does NOT match password!\n"); + return 0; } - fclose(fp); - return 1; + printf("checkpassword(): unexpectedly got to end of function, quitting.\n"); + exit(1); } @@ -7,12 +7,19 @@ #define MAXCHAR 1000 -int readnames(char *nick, char *username, char *realname); +// Sets 'dest' to the value of the configuration option with name +// 'confname' from configuration file 'filename'. +// Returns 1 for success or 0 for error/failure as per what +// getconfstr() returns. +int getconfstr(char *confname, char *filename, char* dest); -int confreplayseconds(); +// Returns the avlue of the configuration option with name +// 'confname' from configuration file 'filename'. +int getconfint(char *confname, char *filename); -int checkpassword(char *password); - -int confclientport(char *port); +// Check the password provided in the string 'str' against what is in +// the configuration file 'filename'. +// Return 0 for password mismatch, or 1 for password match. +int checkpassword(char *password, char *filename); #endif diff --git a/functions.c b/functions.c index c6bea40..1d7d7d6 100644 --- a/functions.c +++ b/functions.c @@ -66,7 +66,6 @@ void stripprefix(char *string) { // Copy the old string into a new one, but... for (size_t i = 1; i < strlen(string); i++) { - printf("i: %zd. strlen: %zd.\n", i, strlen(string)); string2[i - 1] = string[i]; } @@ -98,7 +97,6 @@ void extractfinalparameter(char *string) { // Find the colon for (size_t i = 0; i < strlen(string); i++) { - printf("i: %zd. strlen: %zd.\n", i, strlen(string)); if (string[i] == ':') { printf("Found colon at position %zd!\n", i); colonpos = i; @@ -114,7 +112,6 @@ void extractfinalparameter(char *string) { // Build a new string starting from the next position after the colon int counter = 0; for (size_t i = colonpos + 1; i < strlen(string); i++) { - printf("i: %zd. strlen: %zd.\n", i, strlen(string)); string2[counter] = string[i]; counter++; } @@ -144,7 +141,6 @@ void extractnickfromprefix(char *string) { // Find the bang for (size_t i = 0; i < strlen(string); i++) { - printf("i: %zd. strlen: %zd.\n", i, strlen(string)); if (string[i] == '!') { printf("Found bang at position %zd!\n", i); bangpos = i; |