## modules/au/AU_util.c

/* [<][>][^][v][top][bottom][index][help] */

## DEFINITIONS

This source file includes following functions.

1. AU_crypt
2. au_check_password
3. au_check_MD5_password
4. au_check_crypt_MD5_password
5. au_check_PGPkey
6. au_check_from_address
7. au_is_valid_authmethod
8. AU_authorise

       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){
         /* [<][>][^][v][top][bottom][index][help] */
      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)
         /* [<][>][^][v][top][bottom][index][help] */
      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)
         /* [<][>][^][v][top][bottom][index][help] */
      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)
         /* [<][>][^][v][top][bottom][index][help] */
     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){
         /* [<][>][^][v][top][bottom][index][help] */
     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){
         /* [<][>][^][v][top][bottom][index][help] */
     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 )
         /* [<][>][^][v][top][bottom][index][help] */
     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)
         /* [<][>][^][v][top][bottom][index][help] */
     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 }

/* [<][>][^][v][top][bottom][index][help] */