Source File au/AU_util.c

    1    | /***************************************
    2    |   $Revision: 1.21 $
    3    |
    4    |   Authentication utilities
    5    |
    6    |   Status: NOT REVIEWED, TESTED
    7    |
    8    |   Author(s):      Engin Gunduz
    9    |
    10   |   ******************/ /******************
    11   |   Modification History:
    12   |         engin (05/04/2000) Created.
    13   |   ******************/ /******************
    14   |   Copyright (c) 2000,2001,2002                    RIPE NCC
    15   |
    16   |   All Rights Reserved
    17   |
    18   |   Permission to use, copy, modify, and distribute this software and its
    19   |   documentation for any purpose and without fee is hereby granted,
    20   |   provided that the above copyright notice appear in all copies and that
    21   |   both that copyright notice and this permission notice appear in
    22   |   supporting documentation, and that the name of the author not be
    23   |   used in advertising or publicity pertaining to distribution of the
    24   |   software without specific, written prior permission.
    25   |
    26   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    27   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    28   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    29   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    30   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    31   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    32   |  ***************************************/
    33   |
    34   | #include <md5.h>
    35   | #include "AU_util.h"
    36   | #include "dbupdate.h"
    37   | #include "crypt.h"
    38   |
    39   | extern int tracing;
    40   | extern char *authmethods[];
    41   | extern char *crypt(const char *key, const char *salt);
    42   |
    43   | /* AU_crypt is a wrapper around crypt(3) */
    44   | char * AU_crypt(const char *key, const char *setting){
    45   |
    46   |   return crypt(key, setting);
    47   |
    48   | }
    49   |
    50   | /* takes a list of passwords and a crypted password. If any
    51   |    of the passwords in the list is the plaintext of crypted
    52   |    text, then it immediately returns 1. Otherwise, it returns
    53   |    0 */
    54   | int au_check_password(char * crypted_password, GSList * password_list)
    55   | {
    56   |   GSList * password_item = NULL;
    57   |
    58   |   if (tracing )
    59   |   {
    60   |     printf("TRACING: au_check_password is running" );
    61   |   }
    62   |
    63   |   for (password_item = password_list; password_item != NULL; password_item = g_slist_next(password_item ))
    64   |   {
    65   |     /* if the password is correct, return 1 */
    66   |     if (strcmp(crypt((char *)password_item->data, crypted_password), crypted_password) == 0)
    67   |     {
    68   |       if (tracing )
    69   |       {
    70   |         printf("TRACING: au_check_password returning 1\n");
    71   |       }
    72   |       return(1);  /* auth OK */
    73   |     }
    74   |   }
    75   |   /* we couldn't find any correct password. So, return 0 */
    76   |   if (tracing )
    77   |     printf("TRACING: au_check_password returning 0\n");
    78   |   return(0);      /* auth failed */
    79   | }
    80   |
    81   |
    82   |
    83   | /* takes a list of passwords and a MD5 password. If any
    84   |    of the passwords in the list is the plaintext of MD5
    85   |    digest, then it immediately returns 1. Otherwise, it returns
    86   |    0 */
    87   | int au_check_MD5_password(char * MD5_password, GSList * password_list)
    88   | {
    89   |   MD5_CTX md5ctx;
    90   |   unsigned char md5_value[16];
    91   |   int i;
    92   |   GSList * password_item = NULL;
    93   |
    94   |   for (password_item = password_list; password_item != NULL; password_item = g_slist_next(password_item))
    95   |   {
    96   |     /* if the password is correct, return 1 */
    97   |
    98   |     /* check MD5 password */
    99   |     MD5Init(&md5ctx);
    100  |     MD5Update(&md5ctx, (unsigned char *)password_item->data, (unsigned int)strlen((char *)password_item->data));
    101  |     MD5Final(md5_value, &md5ctx);
    102  |
    103  |     /* md5_calc((unsigned char *)md5_value, (unsigned char *)password_item->data, (unsigned int)strlen(password_item->data)); */
    104  |
    105  |     if (tracing )
    106  |     {
    107  |       printf("TRACING: Digest is: ");
    108  |       for (i = 0; i < 32; i++) printf("%02x", md5_value[i]);
    109  |       printf("\n");
    110  |     }
    111  |
    112  |     if ( strncmp((char *)md5_value, MD5_password, 32) == 0)
    113  |     {
    114  |       if (tracing )
    115  |         printf("TRACING: au_check_MD5_password returning 1\n");
    116  |       return(1);  /* auth OK */
    117  |     }
    118  |   }
    119  |   /* we couldn't find any correct password. So, return 0 */
    120  |   if (tracing )
    121  |     printf("TRACING: au_check_MD5_password returning 0\n");
    122  |   return(0);    /* auth failed */
    123  | }
    124  |
    125  |
    126  |
    127  | /* takes a list of plain text passwords and an MD5 crypt password. If any
    128  |    of the passwords in the list is the plaintext of the crypt MD5
    129  |    then it immediately returns 1. Otherwise, it returns 0 */
    130  |
    131  | int au_check_crypt_MD5_password(char * MD5_password, GSList * password_list)
    132  | {
    133  |   int i;
    134  |   char *pw, *cryptpw;
    135  |   char *passwd;
    136  |   char salt[9];
    137  |   GSList * password_item = NULL;
    138  |
    139  |   if (tracing )
    140  |   {
    141  |     printf("TRACING: au_check_crypt_MD5_password is running" );
    142  |   }
    143  |
    144  |   /* find salt in MD5_password ($1$salt$password) */
    145  |   passwd = strdup(MD5_password);
    146  |   pw = strtok(passwd,"$");  /* points to start of string */
    147  |   pw = strtok(NULL,"$");  /* points to start of salt */
    148  |   if ( pw )
    149  |   {
    150  |     strncpy(salt, pw, 8);
    151  |     salt[8] = '\0';
    152  |   }
    153  |   else
    154  |     salt[0] = '\0';
    155  |   free(passwd);
    156  |
    157  |   for (password_item = password_list; password_item != NULL; password_item = g_slist_next(password_item))
    158  |   {
    159  |     /* encrypt plain text password using the salt from the crypted password*/
    160  |     cryptpw = crypt_md5((const char *)password_item->data, (const char *)salt );
    161  |
    162  |     if (tracing )
    163  |     {
    164  |       printf("TRACING: cryptpw is: [%s]\n", cryptpw );
    165  |     }
    166  |
    167  |     if ( strcmp((char *)cryptpw, (char *)MD5_password) == 0)
    168  |     {
    169  |       if (tracing )
    170  |         printf("TRACING: au_check_crypt_MD5_password returning 1\n");
    171  |
    172  |       return(1);  /* auth OK */
    173  |     }
    174  |   }
    175  |   /* we couldn't find any correct password. So, return 0 */
    176  |   if (tracing )
    177  |     printf("TRACING: au_check_crypt_MD5_password returning 0\n");
    178  |
    179  |   return(0);    /* auth failed */
    180  | }
    181  |
    182  |
    183  |
    184  | /* simply compares auth_pgpkeyID & mesg_pgpkeyID and
    185  |    returns 1 if they are the same. */
    186  | int au_check_PGPkey(char * auth_pgpkeyID, /*char * mesg_pgpkeyID*/GSList * mesg_pgpkeyIDs){
    187  |
    188  |   GSList * next = NULL;
    189  |
    190  |   for(next = mesg_pgpkeyIDs; next != NULL; next = g_slist_next(next)){
    191  |     /* if auth_pgpkeyID & mesg_pgpkeyID are the same, return 1 */
    192  |     if(strcmp(auth_pgpkeyID, (char *)next->data) == 0){
    193  |       return(1);
    194  |     }
    195  |   }
    196  |   /* If we reached here, we couldn't find a matching keyID, so return 0 */
    197  |   return(0);
    198  | }
    199  |
    200  |
    201  |
    202  | /* Compares the 'From' address of the message to the regular
    203  |    expression in the 'auth' attribute of the maintainer*/
    204  | int au_check_from_address(char * regexp, char * from_address){
    205  |
    206  |    int status;
    207  |    regex_t re;
    208  |
    209  |    if(from_address == NULL){
    210  |      return(0);
    211  |    }
    212  |    if (regcomp(&re, regexp, REG_EXTENDED|REG_NOSUB|REG_ICASE) != 0) {
    213  |      //printf("DEBUG: au_check_from_address  returns 0 (couldn't compile)\n");
    214  |      return(0);      /* couldn't compile the regexp, return false */
    215  |    }
    216  |
    217  |    status = regexec(&re, from_address, (size_t) 0, NULL, 0);
    218  |    regfree(&re);
    219  |    if (status != 0) {
    220  |      //printf("DEBUG: au_check_from_address returns 0 (regexp doesn't match)\n\t[regexp:%s][from:%s]\n",
    221  |      //       regexp, from_address);
    222  |      return(0);      /* failed */
    223  |    }
    224  |    /* OK, the regexp matches */
    225  |    //printf("DEBUG: au_check_from_address returns 1\n");
    226  |    return(1);
    227  | }
    228  |
    229  |
    230  | int au_is_valid_authmethod( int type )
    231  | {
    232  |   char *authtype = NULL;
    233  |   int i;
    234  |
    235  |   switch (type)
    236  |   {
    237  |     case AU_NONE:      authtype = strdup("NONE");
    238  |                        break;
    239  |     case AU_MAIL_FROM: authtype = strdup("MAIL-FROM");
    240  |                        break;
    241  |     case AU_CRYPT_PW:  authtype = strdup("CRYPT-PW");
    242  |                        break;
    243  |     case AU_MD5_PW:    authtype = strdup("MD5-PW");
    244  |                        break;
    245  |     case AU_PGP:       authtype = strdup("PGPKEY");
    246  |                        break;
    247  |     default:           authtype = strdup("");
    248  |                        break;
    249  |   }
    250  |
    251  |   i=0;
    252  |   while ( authmethods[i] != NULL )
    253  |   {
    254  |     /* check if the authtype from the mntners is in the list of valid authmethods */
    255  |     if ( ! strcmp(authmethods[i++], authtype) )
    256  |     {
    257  |       free(authtype);
    258  |       return 1;
    259  |     }
    260  |   }
    261  |
    262  |   /* authtype is not a valid authmethod */
    263  |   return 0;
    264  | }
    265  |
    266  |
    267  |
    268  |
    269  | /* Gets a auth_vector, and  credentials_struct (which is extracted
    270  |    from the update message) and returns 0 if all of the auth
    271  |    methods fail, and returns the index of the succeeding auth_struct in the auth_vector
    272  |    if any one of them succeeds. */
    273  | int AU_authorise(GSList * auth_vector, credentials_struct credentials)
    274  | {
    275  |   GSList *auth_item = NULL;
    276  |   auth_struct * temp = NULL;
    277  |   int result = 0;
    278  |
    279  |   /* if the linked list contains no members, then return 1*/
    280  |   if (g_slist_length(auth_vector) == 0)
    281  |   {
    282  |     return(1);
    283  |   }
    284  |
    285  |   for (auth_item = auth_vector; auth_item != NULL; auth_item = g_slist_next(auth_item))
    286  |   {
    287  |     temp = (auth_struct *)auth_item->data;
    288  |     if ( temp != NULL )
    289  |     {
    290  |       if ( au_is_valid_authmethod(temp->type) )
    291  |       {
    292  |         switch (temp->type)
    293  |         {
    294  |           case AU_NONE:      return temp->index; /* NONE, immediately returns true */
    295  |                              break;
    296  |           case AU_MAIL_FROM:
    297  |                              if (au_check_from_address(temp->auth, credentials.from))
    298  |                              {
    299  |                                result = temp->index;
    300  |                              }
    301  |                              break;
    302  |           case AU_CRYPT_PW:  if (au_check_password(temp->auth, credentials.password_list))
    303  |                              {
    304  |                                result = temp->index;
    305  |                              }
    306  |                              break;
    307  |           case AU_MD5_PW:    if (au_check_crypt_MD5_password(temp->auth, credentials.password_list))
    308  |                              {
    309  |                                result = temp->index;
    310  |                              }
    311  |                              break;
    312  |           case AU_PGP:       //printf("DEBUG: AU_authorise: will call au_check_PGPkey\n");
    313  |                              //printf("DEBUG: AU_authorise:   with temp->auth=[%s]\n", temp->auth);
    314  |                              //printf("DEBUG: AU_authorise:   and credentials.pgp_struct=[%s]\n", credentials.pgp_struct);
    315  |                              if (au_check_PGPkey(temp->auth, credentials.pgp_key_list))
    316  |                              {
    317  |                                result = temp->index;
    318  |                              }
    319  |                              break;
    320  |           default:           ;/* this mustn't happen */
    321  |                              break;
    322  |         }
    323  |       }
    324  |       if (result > 0)
    325  |       {
    326  |         return(result);
    327  |       }
    328  |     }
    329  |   }
    330  |
    331  |
    332  |   return 0;
    333  | }