123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // ensure we get the posix version of dirname by including this first
- #include <libgen.h>
- #include "configuration.h"
- #include "task-controller.h"
- #include <errno.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #define INCREMENT_SIZE 1000
- #define MAX_SIZE 10
- struct confentry {
- const char *key;
- const char *value;
- };
- struct configuration {
- int size;
- struct confentry **confdetails;
- };
- struct configuration config={.size=0, .confdetails=NULL};
- //clean up method for freeing configuration
- void free_configurations() {
- int i = 0;
- for (i = 0; i < config.size; i++) {
- if (config.confdetails[i]->key != NULL) {
- free((void *)config.confdetails[i]->key);
- }
- if (config.confdetails[i]->value != NULL) {
- free((void *)config.confdetails[i]->value);
- }
- free(config.confdetails[i]);
- }
- if (config.size > 0) {
- free(config.confdetails);
- }
- config.size = 0;
- }
- /**
- * Is the file/directory only writable by root.
- * Returns 1 if true
- */
- static int is_only_root_writable(const char *file) {
- struct stat file_stat;
- if (stat(file, &file_stat) != 0) {
- fprintf(LOGFILE, "Can't stat file %s - %s\n", file, strerror(errno));
- return 0;
- }
- if (file_stat.st_uid != 0) {
- fprintf(LOGFILE, "File %s must be owned by root, but is owned by %d\n",
- file, file_stat.st_uid);
- return 0;
- }
- if ((file_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
- fprintf(LOGFILE,
- "File %s must not be world or group writable, but is %03o\n",
- file, file_stat.st_mode & (~S_IFMT));
- return 0;
- }
- return 1;
- }
- /**
- * Ensure that the configuration file and all of the containing directories
- * are only writable by root. Otherwise, an attacker can change the
- * configuration and potentially cause damage.
- * returns 0 if permissions are ok
- */
- int check_configuration_permissions(const char* file_name) {
- // copy the input so that we can modify it with dirname
- char* dir = strdup(file_name);
- char* buffer = dir;
- do {
- if (!is_only_root_writable(dir)) {
- free(buffer);
- return -1;
- }
- dir = dirname(dir);
- } while (strcmp(dir, "/") != 0);
- free(buffer);
- return 0;
- }
- //function used to load the configurations present in the secure config
- void read_config(const char* file_name) {
- fprintf(LOGFILE, "Reading task controller config from %s\n" , file_name);
- FILE *conf_file;
- char *line;
- char *equaltok;
- char *temp_equaltok;
- size_t linesize = 1000;
- int size_read = 0;
- if (file_name == NULL) {
- fprintf(LOGFILE, "Null configuration filename passed in\n");
- exit(INVALID_CONFIG_FILE);
- }
- #ifdef DEBUG
- fprintf(LOGFILE, "read_config :Conf file name is : %s \n", file_name);
- #endif
- //allocate space for ten configuration items.
- config.confdetails = (struct confentry **) malloc(sizeof(struct confentry *)
- * MAX_SIZE);
- config.size = 0;
- conf_file = fopen(file_name, "r");
- if (conf_file == NULL) {
- fprintf(LOGFILE, "Invalid conf file provided : %s \n", file_name);
- exit(INVALID_CONFIG_FILE);
- }
- while(!feof(conf_file)) {
- line = (char *) malloc(linesize);
- if(line == NULL) {
- fprintf(LOGFILE, "malloc failed while reading configuration file.\n");
- exit(OUT_OF_MEMORY);
- }
- size_read = getline(&line,&linesize,conf_file);
- //feof returns true only after we read past EOF.
- //so a file with no new line, at last can reach this place
- //if size_read returns negative check for eof condition
- if (size_read == -1) {
- if(!feof(conf_file)){
- fprintf(LOGFILE, "getline returned error.\n");
- exit(INVALID_CONFIG_FILE);
- }else {
- free(line);
- break;
- }
- }
- //trim the ending new line
- line[strlen(line)-1] = '\0';
- //comment line
- if(line[0] == '#') {
- free(line);
- continue;
- }
- //tokenize first to get key and list of values.
- //if no equals is found ignore this line, can be an empty line also
- equaltok = strtok_r(line, "=", &temp_equaltok);
- if(equaltok == NULL) {
- free(line);
- continue;
- }
- config.confdetails[config.size] = (struct confentry *) malloc(
- sizeof(struct confentry));
- if(config.confdetails[config.size] == NULL) {
- fprintf(LOGFILE,
- "Failed allocating memory for single configuration item\n");
- goto cleanup;
- }
- #ifdef DEBUG
- fprintf(LOGFILE, "read_config : Adding conf key : %s \n", equaltok);
- #endif
- memset(config.confdetails[config.size], 0, sizeof(struct confentry));
- config.confdetails[config.size]->key = (char *) malloc(
- sizeof(char) * (strlen(equaltok)+1));
- strcpy((char *)config.confdetails[config.size]->key, equaltok);
- equaltok = strtok_r(NULL, "=", &temp_equaltok);
- if (equaltok == NULL) {
- fprintf(LOGFILE, "configuration tokenization failed \n");
- goto cleanup;
- }
- //means value is commented so don't store the key
- if(equaltok[0] == '#') {
- free(line);
- free((void *)config.confdetails[config.size]->key);
- free(config.confdetails[config.size]);
- continue;
- }
- #ifdef DEBUG
- fprintf(LOGFILE, "read_config : Adding conf value : %s \n", equaltok);
- #endif
- config.confdetails[config.size]->value = (char *) malloc(
- sizeof(char) * (strlen(equaltok)+1));
- strcpy((char *)config.confdetails[config.size]->value, equaltok);
- if((config.size + 1) % MAX_SIZE == 0) {
- config.confdetails = (struct confentry **) realloc(config.confdetails,
- sizeof(struct confentry **) * (MAX_SIZE + config.size));
- if (config.confdetails == NULL) {
- fprintf(LOGFILE,
- "Failed re-allocating memory for configuration items\n");
- goto cleanup;
- }
- }
- if(config.confdetails[config.size] )
- config.size++;
- free(line);
- }
- //close the file
- fclose(conf_file);
- if (config.size == 0) {
- fprintf(LOGFILE, "Invalid configuration provided in %s\n", file_name);
- exit(INVALID_CONFIG_FILE);
- }
- //clean up allocated file name
- return;
- //free spaces alloced.
- cleanup:
- if (line != NULL) {
- free(line);
- }
- fclose(conf_file);
- free_configurations();
- return;
- }
- /*
- * function used to get a configuration value.
- * The function for the first time populates the configuration details into
- * array, next time onwards used the populated array.
- *
- */
- char * get_value(const char* key) {
- int count;
- for (count = 0; count < config.size; count++) {
- if (strcmp(config.confdetails[count]->key, key) == 0) {
- return strdup(config.confdetails[count]->value);
- }
- }
- return NULL;
- }
- /**
- * Function to return an array of values for a key.
- * Value delimiter is assumed to be a comma.
- */
- char ** get_values(const char * key) {
- char ** toPass = NULL;
- char *value = get_value(key);
- char *tempTok = NULL;
- char *tempstr = NULL;
- int size = 0;
- int toPassSize = MAX_SIZE;
- //first allocate any array of 10
- if(value != NULL) {
- toPass = (char **) malloc(sizeof(char *) * toPassSize);
- tempTok = strtok_r((char *)value, ",", &tempstr);
- while (tempTok != NULL) {
- toPass[size++] = tempTok;
- if(size == toPassSize) {
- toPassSize += MAX_SIZE;
- toPass = (char **) realloc(toPass,(sizeof(char *) *
- (MAX_SIZE * toPassSize)));
- }
- tempTok = strtok_r(NULL, ",", &tempstr);
- }
- }
- if (size > 0) {
- toPass[size] = NULL;
- }
- return toPass;
- }
- // free an entry set of values
- void free_values(char** values) {
- if (*values != NULL) {
- free(*values);
- }
- if (values != NULL) {
- free(values);
- }
- }
|