1 /*****************************************************************************/
2 /* */
3 /* (C) Copyright 1995 Alberto Pasquale */
4 /* Portions (C) Copyright 1999 Per Lundberg */
5 /* */
6 /* A L L R I G H T S R E S E R V E D */
7 /* */
8 /*****************************************************************************/
9 /* */
10 /* This source code is NOT in the public domain and it CANNOT be used or */
11 /* distributed without written permission from the author. */
12 /* */
13 /*****************************************************************************/
14 /* */
15 /* How to contact the author: Alberto Pasquale of 2:332/504@fidonet */
16 /* Viale Verdi 106 */
17 /* 41100 Modena */
18 /* Italy */
19 /* */
20 /*****************************************************************************/
21
22 // MaxAcs.Cpp
23
24 #include "bbsgenlb.hpp"
25 #include "uclass.h"
26 #include <apgenlib.hpp>
27 #include <string.h>
28 #include <ctype.h>
29
30 #define _LEVELSIZE 80 // max length of access level name
31 #define _TOKACSSIZE 160 // max length of "<=Normal/a!b"
32 #define _PRODACSSIZE 512 // max length of TOKACS separated by '&'
33
34 // returns 0 on success. keys0 are the keys preceded by '!'
35
GetKeys(char * ks,dword * keys1,dword * keys0=NULL)36 static int GetKeys (char *ks, dword *keys1, dword *keys0 = NULL)
37 {
38 char *c;
39 int u, nbit;
40 long bit;
41
42 BOOL flag0 = FALSE;
43 *keys1 = 0L;
44 if (keys0)
45 *keys0 = 0L;
46
47 for (c = ks; (u = toupper(*c)) != 0; c++)
48 {
49 if ((keys0) && (u == '!')) {
50 flag0 = TRUE;
51 continue;
52 }
53
54 if ((u < '1') || (u > 'X') || (u > '8') && (u < 'A'))
55 return -1;
56
57 if (isdigit (u))
58 nbit = u - '1';
59 else
60 nbit = u - 'A' + 8;
61
62 bit = 1L << nbit;
63
64 if (flag0) {
65 *keys0 |= bit;
66 flag0 = FALSE;
67 } else
68 *keys1 |= bit;
69 }
70 return 0;
71 }
72
73
MAXACS()74 MAXACS::MAXACS ()
75 {
76 buffer = NULL;
77 }
78
79
~MAXACS()80 MAXACS::~MAXACS ()
81 {
82 if (buffer)
83 delete[] buffer;
84 }
85
86
Read(char * acsname)87 int MAXACS::Read (char *acsname)
88 {
89 char fullname[PATH_MAX];
90 strcpy (fullname, acsname);
91 addext (fullname, ".DAT");
92
93 FILE *f = fopen (fullname, "rb");
94 if (!f)
95 return -1;
96 long fsize = filelength (fileno (f));
97 if ((fsize == -1) || (fsize < (long)sizeof (CLSHDR))) {
98 fclose (f);
99 return -1;
100 }
101
102 buffer = new byte[fsize];
103
104 if (fread (buffer, (size_t)fsize, 1, f) != 1) {
105 fclose (f);
106 return -1;
107 }
108
109 fclose (f);
110
111 CLSHDR *chp = (CLSHDR *) buffer;
112 if (chp->ulclhid != CLS_ID)
113 return -1;
114
115 usn = chp->usn;
116 ussize = chp->ussize;
117
118 int heapofs = chp->usclfirst + usn * ussize;
119
120 if (fsize < (heapofs + chp->usstr))
121 return -1;
122
123 heap = (char *) (buffer + heapofs);
124 uscl1 = buffer + chp->usclfirst;
125
126 return 0;
127 }
128
129
GetLevel(char * slevel,word * level)130 int MAXACS::GetLevel (char *slevel, word *level)
131 {
132 byte *b;
133 int i;
134 for (i = 0, b = uscl1; i < usn; i ++, b += ussize) {
135 CLSREC *crp = (CLSREC *) b;
136 if ((stricmp (slevel, heap + crp->zAbbrev) == 0) ||
137 (stricmp (slevel, heap + crp->zAlias) == 0)) {
138 *level = crp->usLevel;
139 return 0;
140 }
141 }
142 return -1;
143 }
144
145
GetGenAcs(char * lks,word * level,dword * keys1,dword * keys0)146 int MAXACS::GetGenAcs (char *lks, word *level, dword *keys1, dword *keys0)
147 {
148 char slevel[_LEVELSIZE];
149
150 char *p = strchr (lks, '/');
151 if (p) { // there are keys
152 strzcpy (slevel, lks, __min (p - lks + 1, _LEVELSIZE));
153 if (keys1)
154 if (GetKeys (p+1, keys1, keys0))
155 return -1;
156 } else {
157 strzcpy (slevel, lks, _LEVELSIZE);
158 if (keys1) {
159 *keys1 = 0L;
160 if (keys0)
161 *keys0 = 0L;
162 }
163 }
164
165 if (isdigit (slevel[0])) { // numeric access level
166 char *endptr;
167 ulong res = strtoul (slevel, &endptr, 10);
168 if ((res > 65535) || (*endptr != '\0'))
169 return -1;
170 *level = (word) res;
171 } else { // string access level: look up access.dat
172 if (GetLevel (slevel, level))
173 return -1;
174 }
175
176 return 0;
177 }
178
179
GetAcs(char * ACS,word * level,dword * keys)180 int MAXACS::GetAcs (char *ACS, word *level, dword *keys)
181 {
182 return GetGenAcs (ACS, level, keys);
183 }
184
185
TokAcs(char * TokAcs,word level,dword keys)186 BOOL MAXACS::TokAcs (char *TokAcs, word level, dword keys)
187 {
188 char *p = TokAcs;
189
190 if (stricmp (p, "NoAccess") == 0)
191 return FALSE;
192 if (strncasecmp (p, "name=", 5) == 0)
193 return FALSE;
194 if (strncasecmp (p, "alias=", 6) == 0)
195 return FALSE;
196
197 _privcmp op;
198
199 switch (strspn (p, "=><!")) { // evaluate comparison operator
200 case 0:
201 op = privGE;
202 break;
203 case 1:
204 if (*p == '=')
205 op = privEQ;
206 else if (*p == '>')
207 op = privGT;
208 else if (*p == '<')
209 op = privLT;
210 else
211 return FALSE;
212 p ++;
213 break;
214 case 2:
215 if ((*p == '>') && (*(p+1) == '='))
216 op = privGE;
217 else if ((*p == '<') && (*(p+1) == '='))
218 op = privLE;
219 else if ((*p == '<') && (*(p+1) == '>'))
220 op = privNE;
221 else if ((*p == '!') && (*(p+1) == '='))
222 op = privNE;
223 else
224 return FALSE;
225 p += 2;
226 break;
227 default:
228 return FALSE;
229 }
230
231 // now evaluate the level/keys
232
233 word reqlevel;
234 dword reqkeys1, reqkeys0;
235
236 if (GetGenAcs (p, &reqlevel, &reqkeys1, &reqkeys0))
237 return FALSE;
238
239 switch (op) { // compare level
240 case privGE:
241 if (!(level >= reqlevel))
242 return FALSE;
243 break;
244 case privLE:
245 if (!(level <= reqlevel))
246 return FALSE;
247 break;
248 case privGT:
249 if (!(level > reqlevel))
250 return FALSE;
251 break;
252 case privLT:
253 if (!(level < reqlevel))
254 return FALSE;
255 break;
256 case privEQ:
257 if (!(level == reqlevel))
258 return FALSE;
259 break;
260 case privNE:
261 if (!(level != reqlevel))
262 return FALSE;
263 break;
264 default:
265 return FALSE;
266 }
267
268 // and now let's check keys
269
270 if ((reqkeys1 & keys) != reqkeys1) // missing some required key
271 return FALSE;
272
273 if ((reqkeys0 & keys) != 0) // has some key that must be absent
274 return FALSE;
275
276 return TRUE;
277 }
278
279
ProdAccess(char * pac,word level,dword keys)280 BOOL MAXACS::ProdAccess (char *pac, word level, dword keys)
281 {
282 char tokacs[_TOKACSSIZE];
283
284 char *p = pac;
285 while (*p) {
286 int toklen = strcspn (p, "&");
287 if (toklen == 0)
288 return FALSE;
289 strzcpy (tokacs, p, __min (toklen + 1, _TOKACSSIZE));
290 if (!TokAcs (tokacs, level, keys))
291 return FALSE;
292 p += toklen;
293 if (*p == '&')
294 p ++;
295 }
296 return TRUE;
297 }
298
299
HaveAccess(char * ACS,word level,dword keys)300 BOOL MAXACS::HaveAccess (char *ACS, word level, dword keys)
301 {
302 char prodacs[_PRODACSSIZE];
303
304 char *p = ACS;
305 while (*p) {
306 int toklen = strcspn (p, "|");
307 if (toklen == 0)
308 return FALSE;
309 strzcpy (prodacs, p, __min (toklen + 1, _PRODACSSIZE));
310 if (ProdAccess (prodacs, level, keys))
311 return TRUE;
312 p += toklen;
313 if (*p == '|')
314 p ++;
315 }
316 return FALSE;
317 }
318
319
LevName(word level)320 char *MAXACS::LevName (word level)
321 {
322 byte *b;
323 int i;
324 for (i = 0, b = uscl1; i < usn; i ++, b += ussize) {
325 CLSREC *crp = (CLSREC *) b;
326 if (level == crp->usLevel)
327 return heap + crp->zAbbrev;
328 }
329 return NULL;
330 }
331
332
LevStr(word level)333 char *MAXACS::LevStr (word level)
334 {
335 char *p = LevName (level);
336 if (p)
337 return p;
338
339 static char buf[6];
340 sprintf (buf, "%hu", level);
341 return buf;
342 }
343
344
345