1    | /***************************************
2    |   $Revision: 1.17 $
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 "AU_util.h"
35   | 
36   | extern char *crypt(const char *key, const char *salt);
37   | 
38   | /* AU_crypt is a wrapper around crypt(3) */
39   | char * AU_crypt(const char *key, const char *setting){
40   | 
41   |   return crypt(key, setting);
42   | 
43   | }
44   | 
45   | /* takes a list of passwords and a crypted password. If any
46   |    of the passwords in the list is the plaintext of crypted
47   |    text, then it immediately returns 1. Otherwise, it returns
48   |    0 */
49   | int au_check_password(char * crypted_password, GSList * password_list){
50   | 
51   |   GSList * next = NULL;
52   | 
53   |   for(next = password_list; next != NULL; next = g_slist_next(next)){
54   |     /* if the password is correct, return 1 */
55   |     if(strcmp(crypt((char *)next->data, crypted_password), crypted_password) == 0){
56   |       //printf("DEBUG: au_check_password returning 1\n");
57   |       return(1);
58   |     }
59   |   }
60   |   /* we couldn't find any correct password. So, return 0 */
61   |   //printf("DEBUG: au_check_password returning 0\n");  
62   |   return(0);  
63   | }
64   | 
65   | 
66   | 
67   | 
68   | /* simply compares auth_pgpkeyID & mesg_pgpkeyID and
69   |    returns 1 if they are the same. */
70   | int au_check_PGPkey(char * auth_pgpkeyID, /*char * mesg_pgpkeyID*/GSList * mesg_pgpkeyIDs){
71   | 
72   |   GSList * next = NULL;
73   | 
74   |   for(next = mesg_pgpkeyIDs; next != NULL; next = g_slist_next(next)){
75   |     /* if auth_pgpkeyID & mesg_pgpkeyID are the same, return 1 */
76   |     if(strcmp(auth_pgpkeyID, (char *)next->data) == 0){
77   |       return(1);
78   |     }
79   |   }
80   |   /* If we reached here, we couldn't find a matching keyID, so return 0 */
81   |   return(0);
82   | }
83   | 
84   | 
85   | 
86   | /* Compares the 'From' address of the message to the regular
87   |    expression in the 'auth' attribute of the maintainer*/
88   | int au_check_from_address(char * regexp, char * from_address){
89   |        
90   |    int status;
91   |    regex_t re;
92   | 
93   |    if(from_address == NULL){
94   |      return(0);
95   |    }
96   |    if (regcomp(&re, regexp, REG_EXTENDED|REG_NOSUB|REG_ICASE) != 0) {
97   |      //printf("DEBUG: au_check_from_address  returns 0 (couldn't compile)\n");
98   |      return(0);      /* couldn't compile the regexp, return false */
99   |    }
100  |    
101  |    status = regexec(&re, from_address, (size_t) 0, NULL, 0);
102  |    regfree(&re);
103  |    if (status != 0) {
104  |      //printf("DEBUG: au_check_from_address returns 0 (regexp doesn't match)\n\t[regexp:%s][from:%s]\n",
105  |      //       regexp, from_address);
106  |      return(0);      /* failed */
107  |    }
108  |    /* OK, the regexp matches */
109  |    //printf("DEBUG: au_check_from_address returns 1\n");
110  |    return(1);
111  | }
112  | 
113  | 
114  | 
115  | 
116  | 
117  | 
118  | 
119  | 
120  | /* Gets a auth_vector, and  credentials_struct (which is extracted
121  |    from the update message) and returns 0 if all of the auth
122  |    methods fail, and returns the index of the succeeding auth_struct in the auth_vector 
123  |    if any one of them succeeds. */
124  | int AU_authorise(GSList * auth_vector, credentials_struct credentials){
125  | 
126  |   GSList * next = NULL;
127  |   auth_struct * temp = NULL;
128  |   int result = 0;
129  | 
130  |   /* if the linked list contains no members, then return 1*/
131  |   if(g_slist_length(auth_vector) == 0){
132  |     return(1);
133  |   }
134  | 
135  |   for(next = auth_vector; next != NULL; next = g_slist_next(next)){
136  |     temp = (auth_struct *)next->data;
137  |     if( temp != NULL ){
138  |       switch (temp->type){
139  |         case AU_NONE: return temp->index; /* NONE, immediately returns true */
140  |         case AU_MAIL_FROM: if(au_check_from_address(temp->auth, credentials.from)){
141  |                              result = temp->index;
142  |                            }
143  |                            break;
144  |         case AU_CRYPT_PW:  if(au_check_password(temp->auth, credentials.password_list)){ 
145  |                              result = temp->index;
146  |                            }
147  |                            break;
148  |         case AU_PGP: //printf("DEBUG: AU_authorise: will call au_check_PGPkey\n");
149  |                      //printf("DEBUG: AU_authorise:   with temp->auth=[%s]\n", temp->auth);
150  |                      //printf("DEBUG: AU_authorise:   and credentials.pgp_struct=[%s]\n", credentials.pgp_struct);
151  |                      if(au_check_PGPkey(temp->auth, credentials.pgp_key_list)){
152  |                        result = temp->index;
153  |                      }
154  |                      break;
155  |         default: ;/* this mustn't happen */
156  |       }
157  |       if(result > 0){
158  |         return(result);
159  |       }
160  |     }
161  |   }
162  |   /* we couldn't find any credential which passes, so returning 0 */
163  |   return 0;  
164  | 
165  | }