configuration.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. // ensure we get the posix version of dirname by including this first
  19. #include <libgen.h>
  20. #include "configuration.h"
  21. #include "task-controller.h"
  22. #include <errno.h>
  23. #include <unistd.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <sys/stat.h>
  28. #include <sys/types.h>
  29. #define INCREMENT_SIZE 1000
  30. #define MAX_SIZE 10
  31. struct confentry {
  32. const char *key;
  33. const char *value;
  34. };
  35. struct configuration {
  36. int size;
  37. struct confentry **confdetails;
  38. };
  39. struct configuration config={.size=0, .confdetails=NULL};
  40. //clean up method for freeing configuration
  41. void free_configurations() {
  42. int i = 0;
  43. for (i = 0; i < config.size; i++) {
  44. if (config.confdetails[i]->key != NULL) {
  45. free((void *)config.confdetails[i]->key);
  46. }
  47. if (config.confdetails[i]->value != NULL) {
  48. free((void *)config.confdetails[i]->value);
  49. }
  50. free(config.confdetails[i]);
  51. }
  52. if (config.size > 0) {
  53. free(config.confdetails);
  54. }
  55. config.size = 0;
  56. }
  57. /**
  58. * Is the file/directory only writable by root.
  59. * Returns 1 if true
  60. */
  61. static int is_only_root_writable(const char *file) {
  62. struct stat file_stat;
  63. if (stat(file, &file_stat) != 0) {
  64. fprintf(LOGFILE, "Can't stat file %s - %s\n", file, strerror(errno));
  65. return 0;
  66. }
  67. if (file_stat.st_uid != 0) {
  68. fprintf(LOGFILE, "File %s must be owned by root, but is owned by %d\n",
  69. file, file_stat.st_uid);
  70. return 0;
  71. }
  72. if ((file_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
  73. fprintf(LOGFILE,
  74. "File %s must not be world or group writable, but is %03o\n",
  75. file, file_stat.st_mode & (~S_IFMT));
  76. return 0;
  77. }
  78. return 1;
  79. }
  80. /**
  81. * Ensure that the configuration file and all of the containing directories
  82. * are only writable by root. Otherwise, an attacker can change the
  83. * configuration and potentially cause damage.
  84. * returns 0 if permissions are ok
  85. */
  86. int check_configuration_permissions(const char* file_name) {
  87. // copy the input so that we can modify it with dirname
  88. char* dir = strdup(file_name);
  89. char* buffer = dir;
  90. do {
  91. if (!is_only_root_writable(dir)) {
  92. free(buffer);
  93. return -1;
  94. }
  95. dir = dirname(dir);
  96. } while (strcmp(dir, "/") != 0);
  97. free(buffer);
  98. return 0;
  99. }
  100. //function used to load the configurations present in the secure config
  101. void read_config(const char* file_name) {
  102. fprintf(LOGFILE, "Reading task controller config from %s\n" , file_name);
  103. FILE *conf_file;
  104. char *line;
  105. char *equaltok;
  106. char *temp_equaltok;
  107. size_t linesize = 1000;
  108. int size_read = 0;
  109. if (file_name == NULL) {
  110. fprintf(LOGFILE, "Null configuration filename passed in\n");
  111. exit(INVALID_CONFIG_FILE);
  112. }
  113. #ifdef DEBUG
  114. fprintf(LOGFILE, "read_config :Conf file name is : %s \n", file_name);
  115. #endif
  116. //allocate space for ten configuration items.
  117. config.confdetails = (struct confentry **) malloc(sizeof(struct confentry *)
  118. * MAX_SIZE);
  119. config.size = 0;
  120. conf_file = fopen(file_name, "r");
  121. if (conf_file == NULL) {
  122. fprintf(LOGFILE, "Invalid conf file provided : %s \n", file_name);
  123. exit(INVALID_CONFIG_FILE);
  124. }
  125. while(!feof(conf_file)) {
  126. line = (char *) malloc(linesize);
  127. if(line == NULL) {
  128. fprintf(LOGFILE, "malloc failed while reading configuration file.\n");
  129. exit(OUT_OF_MEMORY);
  130. }
  131. size_read = getline(&line,&linesize,conf_file);
  132. //feof returns true only after we read past EOF.
  133. //so a file with no new line, at last can reach this place
  134. //if size_read returns negative check for eof condition
  135. if (size_read == -1) {
  136. if(!feof(conf_file)){
  137. fprintf(LOGFILE, "getline returned error.\n");
  138. exit(INVALID_CONFIG_FILE);
  139. }else {
  140. free(line);
  141. break;
  142. }
  143. }
  144. //trim the ending new line
  145. line[strlen(line)-1] = '\0';
  146. //comment line
  147. if(line[0] == '#') {
  148. free(line);
  149. continue;
  150. }
  151. //tokenize first to get key and list of values.
  152. //if no equals is found ignore this line, can be an empty line also
  153. equaltok = strtok_r(line, "=", &temp_equaltok);
  154. if(equaltok == NULL) {
  155. free(line);
  156. continue;
  157. }
  158. config.confdetails[config.size] = (struct confentry *) malloc(
  159. sizeof(struct confentry));
  160. if(config.confdetails[config.size] == NULL) {
  161. fprintf(LOGFILE,
  162. "Failed allocating memory for single configuration item\n");
  163. goto cleanup;
  164. }
  165. #ifdef DEBUG
  166. fprintf(LOGFILE, "read_config : Adding conf key : %s \n", equaltok);
  167. #endif
  168. memset(config.confdetails[config.size], 0, sizeof(struct confentry));
  169. config.confdetails[config.size]->key = (char *) malloc(
  170. sizeof(char) * (strlen(equaltok)+1));
  171. strcpy((char *)config.confdetails[config.size]->key, equaltok);
  172. equaltok = strtok_r(NULL, "=", &temp_equaltok);
  173. if (equaltok == NULL) {
  174. fprintf(LOGFILE, "configuration tokenization failed \n");
  175. goto cleanup;
  176. }
  177. //means value is commented so don't store the key
  178. if(equaltok[0] == '#') {
  179. free(line);
  180. free((void *)config.confdetails[config.size]->key);
  181. free(config.confdetails[config.size]);
  182. continue;
  183. }
  184. #ifdef DEBUG
  185. fprintf(LOGFILE, "read_config : Adding conf value : %s \n", equaltok);
  186. #endif
  187. config.confdetails[config.size]->value = (char *) malloc(
  188. sizeof(char) * (strlen(equaltok)+1));
  189. strcpy((char *)config.confdetails[config.size]->value, equaltok);
  190. if((config.size + 1) % MAX_SIZE == 0) {
  191. config.confdetails = (struct confentry **) realloc(config.confdetails,
  192. sizeof(struct confentry **) * (MAX_SIZE + config.size));
  193. if (config.confdetails == NULL) {
  194. fprintf(LOGFILE,
  195. "Failed re-allocating memory for configuration items\n");
  196. goto cleanup;
  197. }
  198. }
  199. if(config.confdetails[config.size] )
  200. config.size++;
  201. free(line);
  202. }
  203. //close the file
  204. fclose(conf_file);
  205. if (config.size == 0) {
  206. fprintf(LOGFILE, "Invalid configuration provided in %s\n", file_name);
  207. exit(INVALID_CONFIG_FILE);
  208. }
  209. //clean up allocated file name
  210. return;
  211. //free spaces alloced.
  212. cleanup:
  213. if (line != NULL) {
  214. free(line);
  215. }
  216. fclose(conf_file);
  217. free_configurations();
  218. return;
  219. }
  220. /*
  221. * function used to get a configuration value.
  222. * The function for the first time populates the configuration details into
  223. * array, next time onwards used the populated array.
  224. *
  225. */
  226. char * get_value(const char* key) {
  227. int count;
  228. for (count = 0; count < config.size; count++) {
  229. if (strcmp(config.confdetails[count]->key, key) == 0) {
  230. return strdup(config.confdetails[count]->value);
  231. }
  232. }
  233. return NULL;
  234. }
  235. /**
  236. * Function to return an array of values for a key.
  237. * Value delimiter is assumed to be a comma.
  238. */
  239. char ** get_values(const char * key) {
  240. char ** toPass = NULL;
  241. char *value = get_value(key);
  242. char *tempTok = NULL;
  243. char *tempstr = NULL;
  244. int size = 0;
  245. int toPassSize = MAX_SIZE;
  246. //first allocate any array of 10
  247. if(value != NULL) {
  248. toPass = (char **) malloc(sizeof(char *) * toPassSize);
  249. tempTok = strtok_r((char *)value, ",", &tempstr);
  250. while (tempTok != NULL) {
  251. toPass[size++] = tempTok;
  252. if(size == toPassSize) {
  253. toPassSize += MAX_SIZE;
  254. toPass = (char **) realloc(toPass,(sizeof(char *) *
  255. (MAX_SIZE * toPassSize)));
  256. }
  257. tempTok = strtok_r(NULL, ",", &tempstr);
  258. }
  259. }
  260. if (size > 0) {
  261. toPass[size] = NULL;
  262. }
  263. return toPass;
  264. }
  265. // free an entry set of values
  266. void free_values(char** values) {
  267. if (*values != NULL) {
  268. free(*values);
  269. }
  270. if (values != NULL) {
  271. free(values);
  272. }
  273. }