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

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