cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

conf-file.c (5749B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#include "config.h"
     21
     22#include "conf.h"
     23#include "conf-file.h"
     24#include "conf-parse.h"
     25
     26#include <guacamole/client.h>
     27#include <guacamole/mem.h>
     28#include <guacamole/string.h>
     29
     30#include <errno.h>
     31#include <stdio.h>
     32#include <stdlib.h>
     33#include <string.h>
     34#include <unistd.h>
     35
     36#include <sys/types.h>
     37#include <sys/stat.h>
     38#include <fcntl.h>
     39
     40/**
     41 * Updates the configuration with the given parameter/value pair, flagging
     42 * errors as necessary.
     43 */
     44static int guacd_conf_callback(const char* section, const char* param, const char* value, void* data) {
     45
     46    guacd_config* config = (guacd_config*) data;
     47
     48    /* Network server options */
     49    if (strcmp(section, "server") == 0) {
     50
     51        /* Bind host */
     52        if (strcmp(param, "bind_host") == 0) {
     53            guac_mem_free(config->bind_host);
     54            config->bind_host = guac_strdup(value);
     55            return 0;
     56        }
     57
     58        /* Bind port */
     59        else if (strcmp(param, "bind_port") == 0) {
     60            guac_mem_free(config->bind_port);
     61            config->bind_port = guac_strdup(value);
     62            return 0;
     63        }
     64
     65    }
     66
     67    /* Options related to daemon startup */
     68    else if (strcmp(section, "daemon") == 0) {
     69
     70        /* PID file */
     71        if (strcmp(param, "pid_file") == 0) {
     72            guac_mem_free(config->pidfile);
     73            config->pidfile = guac_strdup(value);
     74            return 0;
     75        }
     76
     77        /* Max log level */
     78        else if (strcmp(param, "log_level") == 0) {
     79
     80            int level = guacd_parse_log_level(value);
     81
     82            /* Invalid log level */
     83            if (level < 0) {
     84                guacd_conf_parse_error = "Invalid log level. Valid levels are: \"trace\", \"debug\", \"info\", \"warning\", and \"error\".";
     85                return 1;
     86            }
     87
     88            /* Valid log level */
     89            config->max_log_level = level;
     90            return 0;
     91
     92        }
     93
     94    }
     95
     96    /* SSL-specific options */
     97    else if (strcmp(section, "ssl") == 0) {
     98#ifdef ENABLE_SSL
     99        /* SSL certificate */
    100        if (strcmp(param, "server_certificate") == 0) {
    101            guac_mem_free(config->cert_file);
    102            config->cert_file = guac_strdup(value);
    103            return 0;
    104        }
    105
    106        /* SSL key */
    107        else if (strcmp(param, "server_key") == 0) {
    108            guac_mem_free(config->key_file);
    109            config->key_file = guac_strdup(value);
    110            return 0;
    111        }
    112#else
    113        guacd_conf_parse_error = "SSL support not compiled in";
    114        return 1;
    115#endif
    116
    117    }
    118
    119    /* If still unhandled, the parameter/section is invalid */
    120    guacd_conf_parse_error = "Invalid parameter or section name";
    121    return 1;
    122
    123}
    124
    125int guacd_conf_parse_file(guacd_config* conf, int fd) {
    126
    127    int chars_read;
    128
    129    char buffer[8192];
    130    int length = 0;
    131
    132    int line = 1;
    133    char* line_start = buffer;
    134    int parsed = 0;
    135
    136    /* Attempt to fill remaining space in buffer */
    137    while ((chars_read = read(fd, buffer + length, sizeof(buffer) -  length)) > 0) {
    138
    139        length += chars_read;
    140
    141        line_start = buffer;
    142
    143        /* Attempt to parse entire buffer */
    144        while ((parsed = guacd_parse_conf(guacd_conf_callback, line_start, length, conf)) > 0) {
    145            line_start += parsed;
    146            length -= parsed;
    147            line++;
    148        }
    149
    150        /* Shift contents to front */
    151        memmove(buffer, line_start, length);
    152
    153    }
    154
    155    /* Handle parse errors */
    156    if (parsed < 0) {
    157        int column = guacd_conf_parse_error_location - line_start + 1;
    158        fprintf(stderr, "Parse error at line %i, column %i: %s.\n",
    159                line, column, guacd_conf_parse_error);
    160        return 1;
    161    }
    162
    163    /* Check for error conditions */
    164    if (chars_read < 0) {
    165        fprintf(stderr, "Error reading configuration: %s\n", strerror(errno));
    166        return 1;
    167    }
    168
    169    /* Read successfully */
    170    return 0;
    171
    172}
    173
    174guacd_config* guacd_conf_load() {
    175
    176    guacd_config* conf = guac_mem_alloc(sizeof(guacd_config));
    177    if (conf == NULL)
    178        return NULL;
    179
    180    /* Load defaults */
    181    conf->bind_host = guac_strdup(GUACD_DEFAULT_BIND_HOST);
    182    conf->bind_port = guac_strdup(GUACD_DEFAULT_BIND_PORT);
    183    conf->pidfile = NULL;
    184    conf->foreground = 0;
    185    conf->print_version = 0;
    186    conf->max_log_level = GUAC_LOG_INFO;
    187
    188#ifdef ENABLE_SSL
    189    conf->cert_file = NULL;
    190    conf->key_file = NULL;
    191#endif
    192
    193    /* Read configuration from file */
    194    int fd = open(GUACD_CONF_FILE, O_RDONLY);
    195    if (fd > 0) {
    196
    197        int retval = guacd_conf_parse_file(conf, fd);
    198        close(fd);
    199
    200        if (retval != 0) {
    201            fprintf(stderr, "Unable to parse \"" GUACD_CONF_FILE "\".\n");
    202            guac_mem_free(conf);
    203            return NULL;
    204        }
    205
    206    }
    207
    208    /* Notify of errors preventing reading */
    209    else if (errno != ENOENT) {
    210        fprintf(stderr, "Unable to open \"" GUACD_CONF_FILE "\": %s\n", strerror(errno));
    211        guac_mem_free(conf);
    212        return NULL;
    213    }
    214
    215    return conf;
    216
    217}
    218