Do not use default HTTPS port 443, because it causes clashes with other services.
[igd2-for-linux:jeevans-deviceprotection.git] / linuxigd2 / src / config.c
1 /** 
2  * This file is part of Nokia InternetGatewayDevice v2 reference implementation
3  * Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies).
4  * Contact: mika.saaranen@nokia.com
5  * Developer(s): jaakko.pasanen@tieto.com, opensource@tieto.com
6  *  
7  * This program is free software: you can redistribute it and/or modify 
8  * it under the terms of the GNU General Public License as published by 
9  * the Free Software Foundation, either version 2 of the License, or 
10  * (at your option) any later version. 
11  * 
12  * This program is distributed in the hope that it will be useful, 
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
15  * GNU General Public License for more details. 
16  * 
17  * You should have received a copy of the GNU General Public License 
18  * along with this program. If not, see http://www.gnu.org/licenses/. 
19  * 
20  */
21  
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <regex.h>
26 #include <sys/stat.h>
27 #include "globals.h"
28
29 #define NMATCH 3
30
31 /**
32  * Get value for argument found in config file.
33  *  
34  * @param var Target string for argument value.
35  * @param varlen Max length of argument value.
36  * @param line Line as string from config file where config option locates.
37  * @param submatch Regexp location of found value.
38  * @return 0
39  */
40 int getConfigOptionArgument(char var[],int varlen, char line[], regmatch_t *submatch)
41 {
42     /* limit buffer operations to varlen - 1 */
43     int match_length = min(submatch[1].rm_eo-submatch[1].rm_so, varlen - 1);
44
45     strncpy(var,&line[submatch[1].rm_so],match_length);
46     // Make sure var[] is null terminated
47     var[match_length] = '\0';
48     return 0;
49 }
50
51 /**
52  * Get value for default duration of portmapping found in config file.
53  *  
54  * @param duration Target long int for argument value.
55  * @param line Line as string from config file where config option locates.
56  * @param submatch Regexp location of found value.
57  * @return 0
58  */
59 int getConfigOptionDuration(long int *duration,char line[], regmatch_t *submatch)
60 {
61     long int dur;
62     int absolute_time = submatch[1].rm_eo-submatch[1].rm_so; // >0 if @ was present
63     char num[NUM_LEN];
64     char *p;
65
66     /* limit buffer operations to NUM_LEN - 1 */
67     unsigned int len = min(submatch[2].rm_eo-submatch[2].rm_so, NUM_LEN - 1);
68
69     strncpy(num, &line[submatch[2].rm_so], len);
70     num[len] = '\0';
71     if ((p=index(num,':'))==NULL)
72     {
73         dur = atol(num);
74     }
75     else
76     {
77         *p++ = '\0';
78         dur = atol(num)*3600 + atol(p)*60;
79     }
80
81     if (dur > MAXIMUM_DURATION)
82         dur = MAXIMUM_DURATION;
83
84     if (absolute_time)
85         dur *= -1;
86     *duration = dur;
87     return 0;
88 }
89
90 /**
91  * Parse config file (upnpd.conf) and set default values for global values.
92  *  
93  * @param vars Struct of global default values.
94  * @return -1 if error, else 0.
95  */
96 int parseConfigFile(globals_p vars)
97 {
98     FILE *conf_file;
99     regmatch_t submatch[NMATCH]; // Stores the regex submatch start and end index
100
101     regex_t re_comment;
102     regex_t re_empty_row;
103     regex_t re_pin_code;
104     regex_t re_admin_passwd;
105     regex_t re_wps_config_methods;
106     regex_t re_iptables_location;
107     regex_t re_debug_mode;
108     regex_t re_create_forward_rules;
109     regex_t re_forward_rules_append;
110     regex_t re_forward_chain_name;
111     regex_t re_prerouting_chain_name;
112     regex_t re_upstream_bitrate;
113     regex_t re_downstream_bitrate;
114     regex_t re_duration;
115     regex_t re_desc_doc;
116     regex_t re_xml_path;
117     regex_t re_listenport;
118     regex_t re_https_listenport;
119     regex_t re_dnsmasq;
120     regex_t re_uci;
121     regex_t re_resolv;
122     regex_t re_dhcrelay;
123     regex_t re_dhcrelay_server;
124     regex_t re_dhcpc;
125     regex_t re_network;
126     regex_t re_advertisement_interval;
127     regex_t re_cert_path;
128     regex_t re_acc_lvl_xml;
129
130     // Make sure all vars are 0 or \0 terminated
131     vars->debug = 0;
132     vars->createForwardRules = 0;
133     vars->forwardRulesAppend = 0;
134     strcpy(vars->pinCode,"");
135     strcpy(vars->adminPassword,"");
136     strcpy(vars->wpsConfigMethods,"");
137     strcpy(vars->iptables,"");
138     strcpy(vars->forwardChainName,"");
139     strcpy(vars->preroutingChainName,"");
140     strcpy(vars->upstreamBitrate,"");
141     strcpy(vars->downstreamBitrate,"");
142     vars->duration = DEFAULT_DURATION;
143     strcpy(vars->descDocName,"");
144     strcpy(vars->xmlPath,"");
145     vars->listenport = 0;
146     vars->httpsListenport = 0;
147     strcpy(vars->dnsmasqCmd, "");
148     strcpy(vars->uciCmd, "");
149     strcpy(vars->resolvConf, "");
150     strcpy(vars->dhcrelayCmd, "");
151     strcpy(vars->dhcrelayServer, "");
152     strcpy(vars->dhcpc, "");
153     strcpy(vars->networkCmd, "");
154     vars->advertisementInterval = ADVERTISEMENT_INTERVAL;
155     strcpy(vars->certPath,"");
156     strcpy(vars->accessLevelXml,"");
157
158     // Regexp to match a comment line
159     regcomp(&re_comment,"^[[:blank:]]*#",0);
160     regcomp(&re_empty_row,"^[[:blank:]]*\r?\n$",REG_EXTENDED);
161
162     // Regexps to match configuration file settings
163     regcomp(&re_pin_code,"pin_code[[:blank:]]*=[[:blank:]]*([[:alnum:][:punct:]_/.]{1,50})",REG_EXTENDED);
164     regcomp(&re_admin_passwd,"admin_password[[:blank:]]*=[[:blank:]]*\"([[:alpha:][:blank:]_/.]{1,50})\"",REG_EXTENDED);
165     regcomp(&re_wps_config_methods,"wps_config_methods[[:blank:]]*=[[:blank:]]*([[:alpha:]_]{1,50})",REG_EXTENDED);
166     regcomp(&re_iptables_location,"iptables_location[[:blank:]]*=[[:blank:]]*\"([^\"]+)\"",REG_EXTENDED);
167     regcomp(&re_debug_mode,"debug_mode[[:blank:]]*=[[:blank:]]*([[:digit:]])",REG_EXTENDED);
168     regcomp(&re_forward_chain_name,"forward_chain_name[[:blank:]]*=[[:blank:]]*([[:alpha:]_-]+)",REG_EXTENDED);
169     regcomp(&re_prerouting_chain_name,"prerouting_chain_name[[:blank:]]*=[[:blank:]]([[:alpha:]_-]+)",REG_EXTENDED);
170     regcomp(&re_create_forward_rules,"create_forward_rules[[:blank:]]*=[[:blank:]]*(yes|no)",REG_EXTENDED);
171     regcomp(&re_forward_rules_append,"forward_rules_append[[:blank:]]*=[[:blank:]]*(yes|no)",REG_EXTENDED);
172     regcomp(&re_upstream_bitrate,"upstream_bitrate[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
173     regcomp(&re_downstream_bitrate,"downstream_bitrate[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
174     regcomp(&re_duration,"duration[[:blank:]]*=[[:blank:]]*(@?)([[:digit:]]+|[[:digit:]]{2,}:[[:digit:]]{2})",REG_EXTENDED);
175     regcomp(&re_desc_doc,"description_document_name[[:blank:]]*=[[:blank:]]*([[:alpha:].]{1,20})",REG_EXTENDED);
176     regcomp(&re_xml_path,"xml_document_path[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
177     regcomp(&re_listenport,"listenport[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
178     regcomp(&re_https_listenport,"https_listenport[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
179     regcomp(&re_dnsmasq,"dnsmasq_script[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
180     regcomp(&re_uci,"uci_command[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
181     regcomp(&re_dhcrelay,"dhcrelay_script[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
182     regcomp(&re_resolv,"resolf_conf[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
183     regcomp(&re_dhcrelay_server,"dhcrelay_server[[:blank:]]*=[[:blank:]]*([[:digit:].:]+)",REG_EXTENDED);
184     regcomp(&re_dhcpc,"dhcpc_cmd[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
185     regcomp(&re_network,"network_script[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
186     regcomp(&re_advertisement_interval,"advertisement_interval[[:blank:]]*=[[:blank:]]*([[:digit:]]+)",REG_EXTENDED);
187     regcomp(&re_cert_path,"certificate_path[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
188     regcomp(&re_acc_lvl_xml,"access_level_xml[[:blank:]]*=[[:blank:]]*([[:alpha:]_/.]{1,50})",REG_EXTENDED);
189
190     if ((conf_file=fopen(CONF_FILE,"r")) != NULL)
191     {
192         char line[MAX_CONFIG_LINE];
193         // Walk through the config file line by line
194         while (fgets(line,MAX_CONFIG_LINE,conf_file) != NULL)
195         {
196             // Check if a comment line or an empty one
197             if ( (0 != regexec(&re_comment,line,0,NULL,0)  )  &&
198                     (0 != regexec(&re_empty_row,line,0,NULL,0))  )
199             {
200                 // Check if pin_code
201                 if (regexec(&re_pin_code,line,NMATCH,submatch,0) == 0)
202                 {
203                     getConfigOptionArgument(vars->pinCode, PIN_SIZE, line, submatch);
204                 }
205                 else if (regexec(&re_admin_passwd,line,NMATCH,submatch,0) == 0)
206                 {
207                     getConfigOptionArgument(vars->adminPassword, OPTION_LEN, line, submatch);
208                 }
209                 else if (regexec(&re_wps_config_methods,line,NMATCH,submatch,0) == 0)
210                 {
211                     getConfigOptionArgument(vars->wpsConfigMethods, WPS_CONFIG_METHODS_SIZE, line, submatch);
212                 }
213                 // Check if iptables_location
214                 else if (regexec(&re_iptables_location,line,NMATCH,submatch,0) == 0)
215                 {
216                     getConfigOptionArgument(vars->iptables, OPTION_LEN, line, submatch);
217                 }
218                 // Check if create_forward_rules
219                 else if (regexec(&re_create_forward_rules,line,NMATCH,submatch,0) == 0)
220                 {
221                     char tmp[4];
222                     getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
223                     vars->createForwardRules = strcmp(tmp,"yes")==0 ? 1 : 0;
224                 }
225                 // Check if forward_rules_append
226                 else if (regexec(&re_forward_rules_append,line,NMATCH,submatch,0) == 0)
227                 {
228                     char tmp[4];
229                     getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
230                     vars->forwardRulesAppend = strcmp(tmp,"yes")==0 ? 1 : 0;
231                 }
232                 // Check forward_chain_name
233                 else if (regexec(&re_forward_chain_name,line,NMATCH,submatch,0) == 0)
234                 {
235                     getConfigOptionArgument(vars->forwardChainName, OPTION_LEN, line, submatch);
236                 }
237                 else if (regexec(&re_debug_mode,line,NMATCH,submatch,0) == 0)
238                 {
239                     char tmp[2];
240                     getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
241                     vars->debug = atoi(tmp);
242                 }
243                 else if (regexec(&re_prerouting_chain_name,line,NMATCH,submatch,0) == 0)
244                 {
245                     getConfigOptionArgument(vars->preroutingChainName, OPTION_LEN, line, submatch);
246                 }
247                 else if (regexec(&re_upstream_bitrate,line,NMATCH,submatch,0) == 0)
248                 {
249                     getConfigOptionArgument(vars->upstreamBitrate, OPTION_LEN, line, submatch);
250                 }
251                 else if (regexec(&re_downstream_bitrate,line,NMATCH,submatch,0) == 0)
252                 {
253                     getConfigOptionArgument(vars->downstreamBitrate, OPTION_LEN, line, submatch);
254                 }
255                 else if (regexec(&re_duration,line,NMATCH,submatch,0) == 0)
256                 {
257                     getConfigOptionDuration(&vars->duration,line,submatch);
258                 }
259                 else if (regexec(&re_desc_doc,line,NMATCH,submatch,0) == 0)
260                 {
261                     getConfigOptionArgument(vars->descDocName, OPTION_LEN, line, submatch);
262                 }
263                 else if (regexec(&re_xml_path,line,NMATCH,submatch,0) == 0)
264                 {
265                     getConfigOptionArgument(vars->xmlPath, OPTION_LEN, line, submatch);
266                 }
267                 else if (regexec(&re_https_listenport,line,NMATCH,submatch,0) == 0)
268                 {
269                     char tmp[6];
270                     getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
271                     vars->httpsListenport = atoi(tmp);
272                 }
273                 else if (regexec(&re_listenport,line,NMATCH,submatch,0) == 0)
274                 {
275                     char tmp[6];
276                     getConfigOptionArgument(tmp,sizeof(tmp),line,submatch);
277                     vars->listenport = atoi(tmp);
278                 }
279                 else if (regexec(&re_dnsmasq,line,NMATCH,submatch,0) == 0)
280                 {
281                     getConfigOptionArgument(vars->dnsmasqCmd, OPTION_LEN, line, submatch);
282                 }
283                 else if (regexec(&re_uci,line,NMATCH,submatch,0) == 0)
284                 {
285                     getConfigOptionArgument(vars->uciCmd, OPTION_LEN, line, submatch);
286                 }
287                 else if (regexec(&re_dhcrelay,line,NMATCH,submatch,0) == 0)
288                 {
289                     getConfigOptionArgument(vars->dhcrelayCmd, OPTION_LEN, line, submatch);
290                 }
291                 else if (regexec(&re_resolv,line,NMATCH,submatch,0) == 0)
292                 {
293                     getConfigOptionArgument(vars->resolvConf, OPTION_LEN, line, submatch);
294                 }
295                 else if (regexec(&re_dhcrelay_server,line,NMATCH,submatch,0) == 0)
296                 {
297                     getConfigOptionArgument(vars->dhcrelayServer, OPTION_LEN, line, submatch);
298                 }
299                 else if (regexec(&re_dhcpc,line,NMATCH,submatch,0) == 0)
300                 {
301                     getConfigOptionArgument(vars->dhcpc, OPTION_LEN, line, submatch);
302                 }
303                 else if (regexec(&re_network,line,NMATCH,submatch,0) == 0)
304                 {
305                     getConfigOptionArgument(vars->networkCmd, OPTION_LEN, line, submatch);
306                 }
307                 else if (regexec(&re_advertisement_interval,line,NMATCH,submatch,0) == 0)
308                 {
309                     char tmp[6];
310                     getConfigOptionArgument(tmp, OPTION_LEN, line, submatch);
311                     vars->advertisementInterval = atoi(tmp);
312                 }
313                 else if (regexec(&re_cert_path,line,NMATCH,submatch,0) == 0)
314                 {
315                     getConfigOptionArgument(vars->certPath, OPTION_LEN, line, submatch);
316                 }
317                 else if (regexec(&re_acc_lvl_xml,line,NMATCH,submatch,0) == 0)
318                 {
319                     getConfigOptionArgument(vars->accessLevelXml, OPTION_LEN, line, submatch);
320                 }
321                 else
322                 {
323                     // We end up here if ther is an unknown config directive
324                     printf("Unknown config line: %s",line);
325                 }
326             }
327         }
328         fclose(conf_file);
329     }
330     regfree(&re_comment);
331     regfree(&re_empty_row);
332     regfree(&re_pin_code);
333     regfree(&re_admin_passwd);
334     regfree(&re_iptables_location);
335     regfree(&re_debug_mode);
336     regfree(&re_create_forward_rules);
337     regfree(&re_forward_rules_append);
338     regfree(&re_forward_chain_name);
339     regfree(&re_prerouting_chain_name);
340     regfree(&re_upstream_bitrate);
341     regfree(&re_downstream_bitrate);
342     regfree(&re_duration);
343     regfree(&re_desc_doc);
344     regfree(&re_xml_path);
345     regfree(&re_listenport);
346     regfree(&re_https_listenport);
347     regfree(&re_dnsmasq);
348     regfree(&re_uci);
349     regfree(&re_dhcrelay);
350     regfree(&re_dhcrelay_server);
351     regfree(&re_resolv);
352     regfree(&re_dhcpc);
353     regfree(&re_network);
354     regfree(&re_advertisement_interval);
355     regfree(&re_cert_path);
356     regfree(&re_acc_lvl_xml);
357
358     // Set default values for options not found in config file
359     if (strnlen(vars->forwardChainName, OPTION_LEN) == 0)
360     {
361         // No forward chain name was set in conf file, set it to default
362         snprintf(vars->forwardChainName, OPTION_LEN, IPTABLES_DEFAULT_FORWARD_CHAIN);
363     }
364     if (strnlen(vars->preroutingChainName, OPTION_LEN) == 0)
365     {
366         // No prerouting chain name was set in conf file, set it to default
367         snprintf(vars->preroutingChainName, OPTION_LEN, IPTABLES_DEFAULT_PREROUTING_CHAIN);
368     }
369     if (strnlen(vars->upstreamBitrate, OPTION_LEN) == 0)
370     {
371         // No upstream_bitrate was found in the conf file, set it to default
372         snprintf(vars->upstreamBitrate, OPTION_LEN, DEFAULT_UPSTREAM_BITRATE);
373     }
374     if (strnlen(vars->downstreamBitrate, OPTION_LEN) == 0)
375     {
376         // No downstream bitrate was found in the conf file, set it to default
377         snprintf(vars->downstreamBitrate, OPTION_LEN, DEFAULT_DOWNSTREAM_BITRATE);
378     }
379     if (strnlen(vars->descDocName, OPTION_LEN) == 0)
380     {
381         snprintf(vars->descDocName, OPTION_LEN, DESC_DOC_DEFAULT);
382     }
383     if (strnlen(vars->xmlPath, OPTION_LEN) == 0)
384     {
385         snprintf(vars->xmlPath, OPTION_LEN, XML_PATH_DEFAULT);
386     }
387     if (strnlen(vars->dnsmasqCmd, OPTION_LEN) == 0)
388     {
389         snprintf(vars->dnsmasqCmd, OPTION_LEN, DNSMASQ_CMD_DEFAULT);
390     }
391     if (strnlen(vars->dhcrelayCmd, OPTION_LEN) == 0)
392     {
393         snprintf(vars->dhcrelayCmd, OPTION_LEN, DHCRELAY_CMD_DEFAULT);
394     }
395     if (strnlen(vars->uciCmd, OPTION_LEN) == 0)
396     {
397         snprintf(vars->uciCmd, OPTION_LEN, UCI_CMD_DEFAULT);
398     }
399     if (strnlen(vars->resolvConf, OPTION_LEN) == 0)
400     {
401         snprintf(vars->resolvConf, OPTION_LEN, RESOLV_CONF_DEFAULT);
402     }
403     if (strnlen(vars->dhcpc, OPTION_LEN) == 0)
404     {
405         snprintf(vars->dhcpc, OPTION_LEN, DHCPC_DEFAULT);
406     }
407     if (strnlen(vars->networkCmd, OPTION_LEN) == 0)
408     {
409         snprintf(vars->networkCmd, OPTION_LEN, NETWORK_CMD_DEFAULT);
410     }
411     if (vars->advertisementInterval < 300) // smaller would mess everything
412     {
413         vars->advertisementInterval = 300;
414     }
415     if (strnlen(vars->certPath, OPTION_LEN) == 0)
416     {
417         snprintf(vars->certPath, OPTION_LEN, CERT_PATH_DEFAULT);
418     }
419     if (strnlen(vars->accessLevelXml, OPTION_LEN) == 0)
420     {
421         snprintf(vars->accessLevelXml, OPTION_LEN, ACCESS_LEVEL_XML_DEFAULT);
422     }
423     if (strnlen(vars->iptables, OPTION_LEN) == 0)
424     {
425         // Can't find the iptables executable, return -1 to
426         // indicate en error
427         return -1;
428     }
429     if (strnlen(vars->adminPassword, OPTION_LEN) == 0)
430     {
431         // Can't find the admin password code, return -1 to
432         // indicate en error
433         return -1;
434     }
435     else
436     {
437         return 0;
438     }
439 }