Happy new year
[idzebra-moved-to-github.git] / util / passwddb.c
1 /* This file is part of the Zebra server.
2    Copyright (C) 1994-2009 Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 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 */
19
20
21 #if HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24
25 #include <string.h>
26 #include <stdio.h>
27
28 #if HAVE_CRYPT_H
29 #include <crypt.h>
30 #endif
31
32 #include <assert.h>
33 #include <yaz/log.h>
34 #include <yaz/xmalloc.h>
35
36 #include <passwddb.h>
37
38 struct passwd_entry {
39     int encrypt_flag;
40     char *name;
41     char *des;
42     struct passwd_entry *next;
43 };
44
45 struct passwd_db {
46     struct passwd_entry *entries;
47 };
48
49 Passwd_db passwd_db_open (void)
50 {
51     struct passwd_db *p = (struct passwd_db *) xmalloc (sizeof(*p));
52     p->entries = 0;
53     return p;
54 }
55
56 static int get_entry (const char **p, char *dst, int max)
57 {       
58     int i = 0;
59     while ((*p)[i] != ':' && (*p)[i])
60         i++;
61     if (i >= max)
62         i = max-1;
63     if (i)
64         memcpy (dst, *p, i);
65     dst[i] = '\0';
66     *p += i;
67     if (*p)
68         (*p)++;
69     return i;
70 }
71
72 static int passwd_db_file_int(Passwd_db db, const char *fname,
73                               int encrypt_flag)
74 {
75     FILE *f;
76     char buf[1024];
77     f = fopen (fname, "r");
78     if (!f)
79         return -1;
80     while (fgets (buf, sizeof(buf)-1, f))
81     {
82         struct passwd_entry *pe;
83         char name[128];
84         char des[128];
85         char *p;
86         const char *cp = buf;
87         if ((p = strchr (buf, '\n')))
88             *p = '\0';
89         get_entry (&cp, name, 128);
90         get_entry (&cp, des, 128);
91
92         pe = (struct passwd_entry *) xmalloc (sizeof(*pe));
93         pe->name = xstrdup (name);
94         pe->des = xstrdup (des);
95         pe->encrypt_flag = encrypt_flag;
96         pe->next = db->entries;
97         db->entries = pe;
98     }
99     fclose (f);
100     return 0;
101 }
102
103 void passwd_db_close(Passwd_db db)
104 {
105     struct passwd_entry *pe = db->entries;
106     while (pe)
107     {
108         struct passwd_entry *pe_next = pe->next;
109         
110         xfree (pe->name);
111         xfree (pe->des);
112         xfree (pe);
113         pe = pe_next;
114     }
115     xfree (db);
116 }
117
118 void passwd_db_show(Passwd_db db)
119 {
120     struct passwd_entry *pe;
121     for (pe = db->entries; pe; pe = pe->next)
122         yaz_log (YLOG_LOG,"%s:%s", pe->name, pe->des);
123 }
124
125 int passwd_db_auth(Passwd_db db, const char *user, const char *pass)
126 {
127     struct passwd_entry *pe;
128
129     assert(db);
130     for (pe = db->entries; pe; pe = pe->next)
131         if (user && !strcmp (user, pe->name))
132             break;
133     if (!pe)
134         return -1;
135     if (!pass)
136         return -2;
137     if (pe->encrypt_flag)
138     {
139 #if HAVE_CRYPT_H
140         const char *des_try;
141         assert(pe->des);
142         if (strlen (pe->des) < 3)
143             return -3;
144
145         if (pe->des[0] != '$') /* Not MD5? (assume DES) */
146         {
147             if (strlen(pass) > 8) /* maximum key length is 8 */
148                 return -2;
149         }
150         des_try = crypt (pass, pe->des);
151
152         assert(des_try);
153         if (strcmp (des_try, pe->des))
154             return -2;
155 #else
156         return -2;
157 #endif
158     }
159     else
160     {
161         assert(pass);
162         assert(pe->des);
163         if (strcmp (pe->des, pass))
164             return -2;
165     }
166     return 0;   
167 }
168
169 int passwd_db_file_crypt(Passwd_db db, const char *fname)
170 {
171 #if HAVE_CRYPT_H
172     return passwd_db_file_int(db, fname, 1);
173 #else
174     return -1;
175 #endif
176 }
177
178 int passwd_db_file_plain(Passwd_db db, const char *fname)
179 {
180     return passwd_db_file_int(db, fname, 0);
181 }
182
183 /*
184  * Local variables:
185  * c-basic-offset: 4
186  * indent-tabs-mode: nil
187  * End:
188  * vim: shiftwidth=4 tabstop=8 expandtab
189  */
190