/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- AU_crypt
- au_check_password
- au_check_MD5_password
- au_check_crypt_MD5_password
- au_check_PGPkey
- au_check_from_address
- au_is_valid_authmethod
- 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 }