LCOV - code coverage report
Current view: top level - cmail-popd - config.c (source / functions) Hit Total Coverage
Test: popd.info Lines: 118 146 80.8 %
Date: 2015-11-25 19:05:59 Functions: 7 7 100.0 %

          Line data    Source code
       1           4 : int config_bind(CONFIGURATION* config, char* directive, char* params){
       2           4 :         char* tokenize_line = NULL;
       3           4 :         char* token = NULL;
       4             : 
       5           4 :         char* bindhost = NULL;
       6           4 :         char* port = NULL;
       7             : 
       8             :         #ifndef CMAIL_NO_TLS
       9           4 :         TLSMODE tls_mode = TLS_NONE;
      10           4 :         char* tls_keyfile = NULL;
      11           4 :         char* tls_certfile = NULL;
      12           4 :         char* tls_priorities = NULL;
      13           4 :         char* tls_dh_paramfile = NULL;
      14             :         #endif
      15             : 
      16           4 :         int listen_fd = -1;
      17           4 :         int listener_slot = -1;
      18           4 :         LISTENER settings = {
      19             :                 #ifndef CMAIL_NO_TLS
      20             :                 .tls_require = false,
      21             :                 #endif
      22             :                 .announce_domain = "cmail-popd"
      23             :         };
      24           4 :         LISTENER* listener_data = NULL;
      25             : 
      26             :         //tokenize line
      27           4 :         bindhost = strtok_r(params, " ", &tokenize_line);
      28             :         do{
      29          32 :                 token = strtok_r(NULL, " ", &tokenize_line);
      30          32 :                 if(token){
      31          28 :                         if(!port){
      32           4 :                                 port = token;
      33             :                         }
      34          24 :                         else if(!strncmp(token, "announce=", 9)){
      35           4 :                                 settings.announce_domain = token + 9;
      36             :                         }
      37             :                         #ifndef CMAIL_NO_TLS
      38          20 :                         else if(!strncmp(token, "cert=", 5)){
      39           4 :                                 tls_certfile = token + 5;
      40             :                         }
      41          16 :                         else if(!strncmp(token, "key=", 4)){
      42           4 :                                 tls_keyfile = token + 4;
      43             :                         }
      44          12 :                         else if(!strncmp(token, "ciphers=", 8)){
      45           4 :                                 tls_priorities = token + 8;
      46             :                         }
      47           8 :                         else if(!strncmp(token, "dhparams=", 9)){
      48           4 :                                 tls_dh_paramfile = token + 9;
      49             :                         }
      50           4 :                         else if(!strcmp(token, "tlsonly")){
      51           2 :                                 tls_mode = TLS_ONLY;
      52             :                         }
      53           2 :                         else if(!strcmp(token, "tlsrequire")){
      54           2 :                                 settings.tls_require = true;
      55             :                         }
      56             :                         #endif
      57             :                         else{
      58           0 :                                 logprintf(config->log, LOG_INFO, "Ignored additional bind parameter %s\n", token);
      59             :                         }
      60             :                 }
      61          32 :         }while(token);
      62             : 
      63             :         #ifndef CMAIL_NO_TLS
      64           4 :         if(tls_keyfile && tls_certfile){
      65           4 :                 if(tls_mode == TLS_NONE){
      66           2 :                         tls_mode = TLS_NEGOTIATE;
      67             :                 }
      68             : 
      69           8 :                 if(tls_init_listener(config->log, &settings, tls_certfile, tls_keyfile, tls_dh_paramfile, tls_priorities) < 0){
      70           0 :                         return -1;
      71             :                 }
      72             :         }
      73           0 :         else if(tls_keyfile || tls_certfile || tls_mode != TLS_NONE){
      74           0 :                 logprintf(config->log, LOG_ERROR, "Need both certificate and key for TLS\n");
      75           0 :                 return -1;
      76             :         }
      77             :         #endif
      78             : 
      79             :         //try to open a listening socket
      80           4 :         listen_fd = network_listener(config->log, bindhost, port);
      81             : 
      82           4 :         if(listen_fd < 0){
      83           0 :                 return -1;
      84             :         }
      85             : 
      86             :         //add the new listener to the pool
      87           4 :         listener_slot = connpool_add(&(config->listeners), listen_fd);
      88           4 :         if(listener_slot >= 0){
      89           4 :                 logprintf(config->log, LOG_INFO, "Bound to %s port %s (slot %d)\n", bindhost, port, listener_slot);
      90             : 
      91             :                 //create listener auxdata
      92           4 :                 config->listeners.conns[listener_slot].aux_data = calloc(1, sizeof(LISTENER));
      93           4 :                 if(!config->listeners.conns[listener_slot].aux_data){
      94           0 :                         logprintf(config->log, LOG_ERROR, "Failed to allocate auxiliary data for listener\n");
      95           0 :                         return -1;
      96             :                 }
      97             : 
      98           4 :                 listener_data = (LISTENER*)config->listeners.conns[listener_slot].aux_data;
      99           4 :                 *listener_data = settings;
     100             : 
     101             :                 //copy data to heap
     102             :                 #ifndef CMAIL_NO_TLS
     103           4 :                 config->listeners.conns[listener_slot].tls_mode = tls_mode;
     104             :                 #endif
     105             : 
     106           4 :                 listener_data->announce_domain = common_strdup(settings.announce_domain);
     107           4 :                 if(!listener_data->announce_domain){
     108           0 :                         logprintf(config->log, LOG_ERROR, "Failed to allocate auxiliary data for listener announce\n");
     109           0 :                         return -1;
     110             :                 }
     111           4 :                 return 0;
     112             :         }
     113             : 
     114           0 :         logprintf(config->log, LOG_ERROR, "Failed to store listen socket\n");
     115           0 :         return -1;
     116             : }
     117             : 
     118           2 : int config_privileges(CONFIGURATION* config, char* directive, char* params){
     119             :         struct passwd* user_info;
     120             :         struct group* group_info;
     121             : 
     122           2 :         errno=0;
     123           2 :         if(!strcmp(directive, "user")){
     124           1 :                 user_info = getpwnam(params);
     125           1 :                 if(!user_info){
     126           0 :                         logprintf(config->log, LOG_ERROR, "Failed to get user info for %s\n", params);
     127           0 :                         return -1;
     128             :                 }
     129           1 :                 config->privileges.uid = user_info->pw_uid;
     130           1 :                 config->privileges.gid = user_info->pw_gid;
     131           1 :                 logprintf(config->log, LOG_DEBUG, "Configured dropped privileges to uid %d gid %d\n", config->privileges.uid, config->privileges.gid);
     132           1 :                 return 0;
     133             :         }
     134           1 :         else if(!strcmp(directive, "group")){
     135           1 :                 group_info = getgrnam(params);
     136           1 :                 if(!group_info){
     137           0 :                         logprintf(config->log, LOG_ERROR, "Failed to get group info for %s\n", params);
     138           0 :                         return -1;
     139             :                 }
     140           1 :                 config->privileges.gid = group_info->gr_gid;
     141           1 :                 logprintf(config->log, LOG_DEBUG, "Configured dropped privileges to gid %d\n", config->privileges.gid);
     142           1 :                 return 0;
     143             :         }
     144           0 :         return -1;
     145             : }
     146             : 
     147           1 : int config_database(CONFIGURATION* config, char* directive, char* params){
     148           1 :         if(config->database.conn){
     149           0 :                 logprintf(config->log, LOG_ERROR, "Can not use %s as master database, another one is already attached\n", params);
     150           0 :                 return -1;
     151             :         }
     152             : 
     153           1 :         config->database.conn = database_open(config->log, params, SQLITE_OPEN_READWRITE);
     154             : 
     155           1 :         return (config->database.conn) ? 0:-1;
     156             : }
     157             : 
     158           2 : int config_logger(CONFIGURATION* config, char* directive, char* params){
     159             :         FILE* log_file;
     160             : 
     161           2 :         if(!strcmp(directive, "verbosity")){
     162           1 :                 config->log.verbosity = strtoul(params, NULL, 10);
     163           1 :                 return 0;
     164             :         }
     165           1 :         else if(!strcmp(directive, "logfile")){
     166           1 :                 log_file = fopen(params, "a");
     167           1 :                 if(!log_file){
     168           0 :                         logprintf(config->log, LOG_ERROR, "Failed to open logfile %s for appending\n", params);
     169           0 :                         return -1;
     170             :                 }
     171           1 :                 config->log.stream = log_file;
     172           1 :                 config->log.log_secondary = true;
     173           1 :                 return 0;
     174             :         }
     175           0 :         return -1;
     176             : }
     177             : 
     178           1 : int config_pidfile(CONFIGURATION* config, char* directive, char* params){
     179           1 :         if(config->pid_file){
     180           0 :                 logprintf(config->log, LOG_ERROR, "Multiple pidfile stanzas read, aborting\n");
     181           0 :                 return -1;
     182             :         }
     183             : 
     184           1 :         config->pid_file = common_strdup(params);
     185             : 
     186           1 :         if(!config->pid_file){
     187           0 :                 logprintf(config->log, LOG_ERROR, "Failed to allocate memory for pidfile path\n");
     188           0 :                 return -1;
     189             :         }
     190           1 :         return 0;
     191             : }
     192             : 
     193          10 : int config_line(void* config_data, char* line){
     194             :         unsigned parameter;
     195          10 :         CONFIGURATION* config = (CONFIGURATION*)config_data;
     196             : 
     197             :         //scan over directive
     198          10 :         for(parameter = 0; (!isspace(line[parameter])) && line[parameter] != 0; parameter++){
     199             :         }
     200             : 
     201          10 :         if(line[parameter] != 0){
     202          10 :                 line[parameter] = 0;
     203          10 :                 parameter++;
     204             :         }
     205             : 
     206             :         //scan for parameter begin
     207          10 :         for(; isspace(line[parameter]); parameter++){
     208             :         }
     209             : 
     210             :         //route directives
     211          10 :         if(!strncmp(line, "bind", 4)){
     212           4 :                 return config_bind(config, line, line + parameter);
     213             :         }
     214             : 
     215           6 :         else if(!strncmp(line, "user", 4) || !strncmp(line, "group", 5)){
     216           2 :                 return config_privileges(config, line, line + parameter);
     217             :         }
     218             : 
     219           4 :         else if(!strncmp(line, "database", 8)){
     220           1 :                 return config_database(config, line, line + parameter);
     221             :         }
     222             : 
     223           3 :         else if(!strncmp(line, "verbosity", 9) || !strncmp(line, "logfile", 7)){
     224           2 :                 return config_logger(config, line, line + parameter);
     225             :         }
     226             : 
     227           1 :         else if(!strncmp(line, "pidfile", 7)){
     228           1 :                 return config_pidfile(config, line, line + parameter);
     229             :         }
     230             : 
     231           0 :         logprintf(config->log, LOG_ERROR, "Unknown configuration directive %s\n", line);
     232           0 :         return -1;
     233             : }
     234             : 
     235           2 : void config_free(CONFIGURATION* config){
     236             :         unsigned i;
     237             :         LISTENER* listener_data;
     238             : 
     239          10 :         for(i = 0; i < config->listeners.count; i++){
     240           8 :                 listener_data = (LISTENER*)config->listeners.conns[i].aux_data;
     241             : 
     242             :                 #ifndef CMAIL_NO_TLS
     243           8 :                 if(config->listeners.conns[i].tls_mode != TLS_NONE){
     244           8 :                         gnutls_certificate_free_credentials(listener_data->tls_cert);
     245           8 :                         gnutls_priority_deinit(listener_data->tls_priorities);
     246           8 :                         gnutls_dh_params_deinit(listener_data->tls_dhparams);
     247             :                 }
     248             :                 #endif
     249           8 :                 free(listener_data->announce_domain);
     250             :         }
     251             : 
     252           2 :         connpool_free(&(config->listeners));
     253           2 :         database_free(config->log, &(config->database));
     254             : 
     255           2 :         if(config->pid_file){
     256           2 :                 free(config->pid_file);
     257             :         }
     258             : 
     259           2 :         if(config->log.stream != stderr){
     260           2 :                 fclose(config->log.stream);
     261           2 :                 config->log.stream = stderr;
     262             :         }
     263           2 : }

Generated by: LCOV version 1.11