Changed user type from an enum to a collection of flags
[tpg/opendispense2.git] / src / cokebank_basic / main.c
1 /*
2  * OpenDispense 2 
3  * UCC (University [of WA] Computer Club) Electronic Accounting System
4  *
5  * cokebank.c - Coke-Bank management
6  *
7  * This file is licenced under the 3-clause BSD Licence. See the file COPYING
8  * for full details.
9  */
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <openssl/sha.h>
15 #include "common.h"
16 #if USE_LDAP
17 # include <ldap.h>
18 #endif
19
20 /*
21  * NOTES:
22  * 
23  * http://linuxdevcenter.com/pub/a/linux/2003/08/14/libldap.html
24  * - Using libldap, the LDAP Client Library 
25  * 
26  */
27
28 // === HACKS ===
29 #define HACK_TPG_NOAUTH 1
30 #define HACK_ROOT_NOAUTH        1
31
32 // === PROTOTYPES ===
33 void    Init_Cokebank(const char *Argument);
34  int    Transfer(int SourceUser, int DestUser, int Ammount, const char *Reason);
35  int    GetBalance(int User);
36 char    *GetUserName(int User);
37  int    GetUserID(const char *Username);
38  int    GetMaxID(void);
39  int    GetUserAuth(const char *Salt, const char *Username, const char *PasswordString);
40 #if USE_LDAP
41 char    *ReadLDAPValue(const char *Filter, char *Value);
42 #endif
43 void    HexBin(uint8_t *Dest, int BufSize, const char *Src);
44
45 // === GLOBALS ===
46 FILE    *gBank_LogFile;
47 #if USE_LDAP
48 char    *gsLDAPPath = "ldapi:///";
49 LDAP    *gpLDAP;
50 #endif
51
52 // === CODE ===
53 /**
54  * \brief Load the cokebank database
55  */
56 void Init_Cokebank(const char *Argument)
57 {
58         #if USE_LDAP
59          int    rv;
60         #endif
61         
62         // Open Cokebank
63         gBank_File = fopen(Argument, "rb+");
64         if( !gBank_File ) {
65                 gBank_File = fopen(Argument, "wb+");
66         }
67         if( !gBank_File ) {
68                 perror("Opening coke bank");
69         }
70
71         // Open log file
72         // TODO: Do I need this?
73         gBank_LogFile = fopen("cokebank.log", "a");
74         if( !gBank_LogFile )    gBank_LogFile = stdout;
75
76         // Read in cokebank
77         fseek(gBank_File, 0, SEEK_END);
78         giBank_NumUsers = ftell(gBank_File) / sizeof(gaBank_Users[0]);
79         fseek(gBank_File, 0, SEEK_SET);
80         gaBank_Users = malloc( giBank_NumUsers * sizeof(gaBank_Users[0]) );
81         fread(gaBank_Users, sizeof(gaBank_Users[0]), giBank_NumUsers, gBank_File);
82         
83         #if USE_LDAP
84         // Connect to LDAP
85         rv = ldap_create(&gpLDAP);
86         if(rv) {
87                 fprintf(stderr, "ldap_create: %s\n", ldap_err2string(rv));
88                 exit(1);
89         }
90         rv = ldap_initialize(&gpLDAP, gsLDAPPath);
91         if(rv) {
92                 fprintf(stderr, "ldap_initialize: %s\n", ldap_err2string(rv));
93                 exit(1);
94         }
95         { int ver = LDAP_VERSION3; ldap_set_option(gpLDAP, LDAP_OPT_PROTOCOL_VERSION, &ver); }
96         # if 0
97         rv = ldap_start_tls_s(gpLDAP, NULL, NULL);
98         if(rv) {
99                 fprintf(stderr, "ldap_start_tls_s: %s\n", ldap_err2string(rv));
100                 exit(1);
101         }
102         # endif
103         {
104                 struct berval   cred;
105                 struct berval   *servcred;
106                 cred.bv_val = "secret";
107                 cred.bv_len = 6;
108                 rv = ldap_sasl_bind_s(gpLDAP, "cn=root,dc=ucc,dc=gu,dc=uwa,dc=edu,dc=au",
109                         "", &cred, NULL, NULL, &servcred);
110                 if(rv) {
111                         fprintf(stderr, "ldap_start_tls_s: %s\n", ldap_err2string(rv));
112                         exit(1);
113                 }
114         }
115         #endif
116 }
117
118 /**
119  * \brief Transfers money from one user to another
120  * \param SourceUser    Source user
121  * \param DestUser      Destination user
122  * \param Ammount       Ammount of cents to move from \a SourceUser to \a DestUser
123  * \param Reason        Reason for the transfer (essentially a comment)
124  * \return Boolean failure
125  */
126 int Transfer(int SourceUser, int DestUser, int Ammount, const char *Reason)
127 {
128          int    srcBal = Bank_GetUserBalance(SourceUser);
129          int    dstBal = Bank_GetUserBalance(DestUser);
130         
131         if( srcBal - Ammount < Bank_GetMinAllowedBalance(SourceUser) )
132                 return 1;
133         if( dstBal + Ammount < Bank_GetMinAllowedBalance(DestUser) )
134                 return 1;
135         Bank_AlterUserBalance(DestUser, Ammount);
136         Bank_AlterUserBalance(SourceUser, -Ammount);
137         fprintf(gBank_LogFile, "ACCT #%i{%i} -= %ic [to #%i] (%s)\n", SourceUser, srcBal, Ammount, DestUser, Reason);
138         fprintf(gBank_LogFile, "ACCT #%i{%i} += %ic [from #%i] (%s)\n", DestUser, dstBal, Ammount, SourceUser, Reason);
139         return 0;
140 }
141
142 int GetFlags(int User)
143 {
144         return Bank_GetUserFlags(User);
145 }
146
147 int SetFlags(int User, int Mask, int Flags)
148 {
149         return Bank_SetUserFlags(User, Mask, Flags);
150 }
151
152 /**
153  * \brief Get the balance of the passed user
154  */
155 int GetBalance(int User)
156 {
157         return Bank_GetUserBalance(User);;
158 }
159
160 /**
161  * \brief Return the name the passed user
162  */
163 char *GetUserName(int User)
164 {
165         return Bank_GetUserName(User);
166 }
167
168 /**
169  * \brief Get the User ID of the named user
170  */
171 int GetUserID(const char *Username)
172 {
173         return Bank_GetUserByName(Username);
174 }
175
176 int CreateUser(const char *Username)
177 {
178          int    ret;
179         
180         ret = Bank_GetUserByName(Username);
181         if( ret != -1 ) return -1;
182         
183         return Bank_AddUser(Username);
184 }
185
186 int GetMaxID(void)
187 {
188         return giBank_NumUsers;
189 }
190
191 /**
192  * \brief Authenticate a user
193  * \return User ID, or -1 if authentication failed
194  */
195 int GetUserAuth(const char *Salt, const char *Username, const char *PasswordString)
196 {
197         #if USE_LDAP
198         uint8_t hash[20];
199         uint8_t h[20];
200          int    ofs = strlen(Username) + strlen(Salt);
201         char    input[ ofs + 40 + 1];
202         char    tmp[4 + strlen(Username) + 1];  // uid=%s
203         char    *passhash;
204         #endif
205         
206         #if HACK_TPG_NOAUTH
207         if( strcmp(Username, "tpg") == 0 )
208                 return GetUserID("tpg");
209         #endif
210         #if HACK_ROOT_NOAUTH
211         if( strcmp(Username, "root") == 0 ) {
212                 int ret = GetUserID("root");
213                 if( ret == -1 )
214                         return CreateUser("root");
215                 return ret;
216         }
217         #endif
218         
219         #if USE_LDAP
220         HexBin(hash, 20, PasswordString);
221         
222         // Build string to hash
223         strcpy(input, Username);
224         strcpy(input, Salt);
225         
226         // TODO: Get user's SHA-1 hash
227         sprintf(tmp, "uid=%s", Username);
228         printf("tmp = '%s'\n", tmp);
229         passhash = ReadLDAPValue(tmp, "userPassword");
230         if( !passhash ) {
231                 return -1;
232         }
233         printf("LDAP hash '%s'\n", passhash);
234         
235         sprintf(input+ofs, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
236                 h[ 0], h[ 1], h[ 2], h[ 3], h[ 4], h[ 5], h[ 6], h[ 7], h[ 8], h[ 9],
237                 h[10], h[11], h[12], h[13], h[14], h[15], h[16], h[17], h[18], h[19]
238                 );
239         // Then create the hash from the provided salt
240         // Compare that with the provided hash
241
242         # if 1
243         {
244                  int    i;
245                 printf("Password hash ");
246                 for(i=0;i<20;i++)
247                         printf("%02x", hash[i]&0xFF);
248                 printf("\n");
249         }
250         # endif
251         
252         #endif
253         
254         return -1;
255 }
256
257 #if USE_LDAP
258 char *ReadLDAPValue(const char *Filter, char *Value)
259 {
260         LDAPMessage     *res, *res2;
261         struct berval **attrValues;
262         char    *attrNames[] = {Value,NULL};
263         char    *ret;
264         struct timeval  timeout;
265          int    rv;
266         
267         timeout.tv_sec = 5;
268         timeout.tv_usec = 0;
269         
270         rv = ldap_search_ext_s(gpLDAP, "", LDAP_SCOPE_BASE, Filter,
271                 attrNames, 0, NULL, NULL, &timeout, 1, &res
272                 );
273         printf("ReadLDAPValue: rv = %i\n", rv);
274         if(rv) {
275                 fprintf(stderr, "LDAP Error reading '%s' with filter '%s'\n%s\n",
276                         Value, Filter,
277                         ldap_err2string(rv)
278                         );
279                 return NULL;
280         }
281         
282         res2 = ldap_first_entry(gpLDAP, res);
283         attrValues = ldap_get_values_len(gpLDAP, res2, Value);
284         
285         ret = strndup(attrValues[0]->bv_val, attrValues[0]->bv_len);
286         
287         ldap_value_free_len(attrValues);
288         
289         
290         return ret;
291 }
292 #endif
293
294 // TODO: Move to another file
295 void HexBin(uint8_t *Dest, int BufSize, const char *Src)
296 {
297          int    i;
298         for( i = 0; i < BufSize; i ++ )
299         {
300                 uint8_t val = 0;
301                 
302                 if('0' <= *Src && *Src <= '9')
303                         val |= (*Src-'0') << 4;
304                 else if('A' <= *Src && *Src <= 'F')
305                         val |= (*Src-'A'+10) << 4;
306                 else if('a' <= *Src && *Src <= 'f')
307                         val |= (*Src-'a'+10) << 4;
308                 else
309                         break;
310                 Src ++;
311                 
312                 if('0' <= *Src && *Src <= '9')
313                         val |= (*Src-'0');
314                 else if('A' <= *Src && *Src <= 'F')
315                         val |= (*Src-'A'+10);
316                 else if('a' <= *Src && *Src <= 'f')
317                         val |= (*Src-'a'+10);
318                 else
319                         break;
320                 Src ++;
321                 
322                 Dest[i] = val;
323         }
324         for( ; i < BufSize; i++ )
325                 Dest[i] = 0;
326 }
327

UCC git Repository :: git.ucc.asn.au