port fix from branch_1_1
[freeradius.git] / src / main / crypt.c
1 /*
2  * crypt.c      A thread-safe crypt wrapper
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation; either version 2 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  *
14  *   You should have received a copy of the GNU General Public License
15  *   along with this program; if not, write to the Free Software
16  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * Copyright 2000-2006  The FreeRADIUS server project
19  */
20
21 #include <freeradius-devel/ident.h>
22 RCSID("$Id$")
23
24 #include <freeradius-devel/autoconf.h>
25 #include <string.h>
26
27 #ifdef HAVE_CRYPT_H
28 #include <crypt.h>
29 #else
30 #include <unistd.h>
31 #endif
32
33 #ifdef HAVE_PTHREAD_H
34 #include <pthread.h>
35
36 /*
37  *  No pthreads, no mutex.
38  */
39 static int lrad_crypt_init = 0;
40 static pthread_mutex_t lrad_crypt_mutex;
41 #endif
42
43 #include <freeradius-devel/missing.h>
44 #include <freeradius-devel/libradius.h>
45
46 /*
47  * performs a crypt password check in an thread-safe way.
48  *
49  * returns:  0 -- check succeeded
50  *          -1 -- failed to crypt
51  *           1 -- check failed
52  */
53 int lrad_crypt_check(const char *key, const char *crypted)
54 {
55         char *passwd;
56         int cmp = 0;
57
58 #ifdef HAVE_PTHREAD_H
59         /*
60          *      Ensure we're thread-safe, as crypt() isn't.
61          */
62         if (lrad_crypt_init == 0) {
63                 pthread_mutex_init(&lrad_crypt_mutex, NULL);
64                 lrad_crypt_init = 1;
65         }
66
67         pthread_mutex_lock(&lrad_crypt_mutex);
68 #endif
69
70         passwd = crypt(key, crypted);
71
72         /*
73          *      Got something, check it within the lock.  This is
74          *      faster than copying it to a local buffer, and the
75          *      time spent within the lock is critical.
76          */
77         if (passwd) {
78                 cmp = strcmp(crypted, passwd);
79         }
80
81 #ifdef HAVE_PTHREAD_H
82         pthread_mutex_unlock(&lrad_crypt_mutex);
83 #endif
84
85         /*
86          *      Error.
87          */
88         if (!passwd) {
89                 return -1;
90         }
91
92         /*
93          *      OK, return OK.
94          */
95         if (cmp == 0) {
96                 return 0;
97         }
98
99         /*
100          *      Comparison failed.
101          */
102         return 1;
103 }