LCOV - code coverage report
Current view: top level - lib - sasl.c (source / functions) Hit Total Coverage
Test: smtpd.info Lines: 55 70 78.6 %
Date: 2015-11-25 19:06:20 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* This file is part of the cmail project (http://cmail.rocks/)
       2             :  * (c) 2015 Fabian "cbdev" Stumpf
       3             :  * License: Simplified BSD (2-Clause)
       4             :  * For further information, consult LICENSE.txt
       5             :  */
       6             : 
       7          21 : void sasl_reset_ctx(SASL_CONTEXT* ctx, bool data_valid){
       8          21 :         SASL_CONTEXT empty = {
       9             :                 .method = SASL_INVALID,
      10             :                 .method_data = NULL,
      11             :                 .user = NULL
      12             :         };
      13             : 
      14          21 :         if(data_valid){
      15           8 :                 if(ctx->method_data){
      16             :                         //FIXME arbitrate this by method
      17           0 :                         free(ctx->method_data);
      18             :                 }
      19             :         }
      20             : 
      21          21 :         *ctx = empty;
      22          21 : }
      23             : 
      24          27 : void sasl_reset_user(SASL_USER* user, bool data_valid){
      25          27 :         SASL_USER empty = {
      26             :                 .authorized = NULL,
      27             :                 .authenticated = NULL
      28             :         };
      29             : 
      30          27 :         if(data_valid){
      31          17 :                 if(user->authorized){
      32           3 :                         free(user->authorized);
      33             :                 }
      34             : 
      35          17 :                 if(user->authenticated){
      36           5 :                         free(user->authenticated);
      37             :                 }
      38             :         }
      39             : 
      40          27 :         *user = empty;
      41          27 : }
      42             : 
      43          10 : SASL_METHOD sasl_scan_method(char* method){
      44          10 :         if(!strncasecmp(method, "plain", 5)){
      45           8 :                 return SASL_PLAIN;
      46             :         }
      47             : 
      48           2 :         return SASL_INVALID;
      49             : }
      50             : 
      51           3 : int sasl_challenge(LOGGER log, SASL_CONTEXT* ctx, char** response){
      52           3 :         switch(ctx->method){
      53             :                 case SASL_PLAIN:
      54           3 :                         *response = NULL;
      55           3 :                         return SASL_CONTINUE;
      56             :                 default:
      57           0 :                         logprintf(log, LOG_ERROR, "No challenge handler defined for SASL method\n");
      58           0 :                         return SASL_ERROR_PROCESSING;
      59             :         }
      60             : 
      61             :         return SASL_ERROR_PROCESSING;
      62             : }
      63             : 
      64           7 : int sasl_continue(LOGGER log, SASL_CONTEXT* ctx, char* data, char** response){
      65           7 :         int length, off_user = 0, off_pass = 0;
      66             : 
      67           7 :         if(!response){
      68           0 :                 logprintf(log, LOG_ERROR, "NULL response pointer in sasl_continue\n");
      69           0 :                 return SASL_ERROR_PROCESSING;
      70             :         }
      71             : 
      72           7 :         switch(ctx->method){
      73             :                 case SASL_PLAIN:
      74           7 :                         if(!data){
      75           0 :                                 return SASL_ERROR_DATA;
      76             :                         }
      77             : 
      78           7 :                         length = auth_base64decode(log, data);
      79             : 
      80           7 :                         if(length < 4){ //2x NUL, 2x min 1 byte
      81           2 :                                 logprintf(log, LOG_ERROR, "Failed to decode PLAIN authentication parameter\n");
      82           2 :                                 return SASL_ERROR_DATA;
      83             :                         }
      84             : 
      85             :                         //RFC 4616 message = [authzid] UTF8NUL authcid UTF8NUL passwd
      86             :                         //TODO test this thoroughly
      87           5 :                         off_user = strlen(data) + 1;
      88           5 :                         if(off_user >= length || strlen(data + off_user) < 1 || off_user + strlen(data + off_user) >= length){
      89           0 :                                 logprintf(log, LOG_ERROR, "SASL PLAIN user read out of bounds\n");
      90           0 :                                 return SASL_ERROR_DATA;
      91             :                         }
      92             : 
      93           5 :                         off_pass = off_user + strlen(data + off_user) + 1;
      94           5 :                         if(off_pass >= length || off_pass + strlen(data + off_pass) >= length){
      95           0 :                                 logprintf(log, LOG_ERROR, "SASL PLAIN pass read out of bounds\n");
      96           0 :                                 return SASL_ERROR_DATA;
      97             :                         }
      98             : 
      99             :                         //FIXME do not print passwords
     100           5 :                         logprintf(log, LOG_DEBUG, "SASL PLAIN user %s pass %s\n", data + off_user, data + off_pass);
     101           5 :                         ctx->user->authenticated = common_strdup(data + off_user);
     102           5 :                         if(!(ctx->user->authenticated)){
     103           0 :                                 logprintf(log, LOG_ERROR, "Failed to allocate memory for authenticated user\n");
     104           0 :                                 return SASL_ERROR_PROCESSING;
     105             :                         }
     106             : 
     107           5 :                         *response = data + off_pass;
     108           5 :                         return SASL_DATA_OK;
     109             :                 default:
     110           0 :                         logprintf(log, LOG_ERROR, "No continuation handler defined for SASL method\n");
     111           0 :                         return SASL_ERROR_PROCESSING;
     112             :         }
     113             : 
     114             :         return SASL_ERROR_PROCESSING;
     115             : }
     116             : 
     117          10 : int sasl_begin(LOGGER log, SASL_CONTEXT* ctx, SASL_USER* user, char* method, char* data, char** response){
     118             :         //sanity check
     119          10 :         if(!ctx || !user || !method || !response){
     120           0 :                 return SASL_ERROR_PROCESSING;
     121             :         }
     122             : 
     123          10 :         sasl_reset_ctx(ctx, false);
     124          10 :         sasl_reset_user(user, false);
     125          10 :         ctx->user = user;
     126             : 
     127             :         //scan method
     128          10 :         ctx->method = sasl_scan_method(method);
     129             : 
     130          10 :         if(ctx->method == SASL_INVALID){
     131           2 :                 return SASL_UNKNOWN_METHOD;
     132             :         }
     133             : 
     134             :         //if initial supplied, handle
     135           8 :         if(data){
     136           5 :                 return sasl_continue(log, ctx, data, response);
     137             :         }
     138             : 
     139           3 :         return sasl_challenge(log, ctx, response);
     140             : }
     141             : 
     142           1 : int sasl_cancel(SASL_CONTEXT* ctx){
     143           1 :         sasl_reset_ctx(ctx, true);
     144           1 :         return 0;
     145             : }

Generated by: LCOV version 1.11