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

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