More attributes as sent in by a nice person at HP
[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/libradius.h>
25
26 #ifdef HAVE_CRYPT_H
27 #include <crypt.h>
28 #endif
29
30 #ifdef HAVE_PTHREAD_H
31 #include <pthread.h>
32
33 /*
34  *  No pthreads, no mutex.
35  */
36 static int fr_crypt_init = 0;
37 static pthread_mutex_t fr_crypt_mutex;
38 #endif
39
40
41 /*
42  * performs a crypt password check in an thread-safe way.
43  *
44  * returns:  0 -- check succeeded
45  *          -1 -- failed to crypt
46  *           1 -- check failed
47  */
48 int fr_crypt_check(const char *key, const char *crypted)
49 {
50         char *passwd;
51         int cmp = 0;
52
53 #ifdef HAVE_PTHREAD_H
54         /*
55          *      Ensure we're thread-safe, as crypt() isn't.
56          */
57         if (fr_crypt_init == 0) {
58                 pthread_mutex_init(&fr_crypt_mutex, NULL);
59                 fr_crypt_init = 1;
60         }
61
62         pthread_mutex_lock(&fr_crypt_mutex);
63 #endif
64
65         passwd = crypt(key, crypted);
66
67         /*
68          *      Got something, check it within the lock.  This is
69          *      faster than copying it to a local buffer, and the
70          *      time spent within the lock is critical.
71          */
72         if (passwd) {
73                 cmp = strcmp(crypted, passwd);
74         }
75
76 #ifdef HAVE_PTHREAD_H
77         pthread_mutex_unlock(&fr_crypt_mutex);
78 #endif
79
80         /*
81          *      Error.
82          */
83         if (!passwd) {
84                 return -1;
85         }
86
87         /*
88          *      OK, return OK.
89          */
90         if (cmp == 0) {
91                 return 0;
92         }
93
94         /*
95          *      Comparison failed.
96          */
97         return 1;
98 }