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] */