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