1 /*
2  * ProFTPD - FTP server daemon
3  * Copyright (c) 2008-2020 The ProFTPD Project team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18  *
19  * As a special exemption, The ProFTPD Project team and other respective
20  * copyright holders give permission to link this program with OpenSSL, and
21  * distribute the resulting executable, without including the source code for
22  * OpenSSL in the source distribution.
23  */
24 
25 /* Expression API implementation */
26 
27 #include "conf.h"
28 
pr_expr_create(pool * p,unsigned int * argc,char ** argv)29 array_header *pr_expr_create(pool *p, unsigned int *argc, char **argv) {
30   array_header *acl = NULL;
31   unsigned int cnt;
32   char *s, *ent;
33 
34   if (p == NULL ||
35       argc == NULL ||
36       argv == NULL ||
37       *argv == NULL) {
38     errno = EINVAL;
39     return NULL;
40   }
41 
42   cnt = *argc;
43 
44   if (cnt > 0) {
45     acl = make_array(p, cnt, sizeof(char *));
46 
47     /* Skip past the first string in argv, as this is usually the directive. */
48     while (cnt-- && *(++argv)) {
49       char *sep = ",";
50 
51       s = pstrdup(p, *argv);
52 
53       if (strstr(s, sep) != NULL) {
54         while ((ent = pr_str_get_token(&s, sep)) != NULL) {
55           pr_signals_handle();
56 
57           if (*ent) {
58             *((char **) push_array(acl)) = ent;
59           }
60         }
61 
62       } else {
63         *((char **) push_array(acl)) = s;
64       }
65     }
66 
67     *argc = acl->nelts;
68 
69   } else {
70     acl = make_array(p, 0, sizeof(char *));
71     *argc = 0;
72   }
73 
74   return acl;
75 }
76 
77 /* Boolean "class-expression" AND matching, returns TRUE if the expression
78  * evaluates to TRUE.
79  */
pr_expr_eval_class_and(char ** expr)80 int pr_expr_eval_class_and(char **expr) {
81   int found;
82   char *class;
83 
84   if (expr == NULL ||
85       *expr == NULL) {
86     errno = EINVAL;
87     return -1;
88   }
89 
90   for (; *expr; expr++) {
91     class = *expr;
92     found = FALSE;
93 
94     if (*class == '!') {
95       found = !found;
96       class++;
97     }
98 
99     if (session.conn_class == NULL &&
100         !found) {
101       return FALSE;
102     }
103 
104     if (session.conn_class != NULL &&
105         strcmp(session.conn_class->cls_name, class) == 0) {
106       found = !found;
107     }
108 
109     if (!found) {
110       return FALSE;
111     }
112   }
113 
114   return TRUE;
115 }
116 
117 /* Boolean "class-expression" OR matching, returns TRUE if the expression
118  * evaluates to TRUE.
119  */
pr_expr_eval_class_or(char ** expr)120 int pr_expr_eval_class_or(char **expr) {
121   int found;
122   char *class;
123 
124   if (expr == NULL ||
125       *expr == NULL) {
126     errno = EINVAL;
127     return -1;
128   }
129 
130   for (; *expr; expr++) {
131     class = *expr;
132     found = FALSE;
133 
134     if (*class == '!') {
135       found = !found;
136       class++;
137     }
138 
139     if (session.conn_class == NULL)
140       return found;
141 
142     if (strcmp(session.conn_class->cls_name, class) == 0)
143       found = !found;
144 
145     if (found)
146       return TRUE;
147   }
148 
149   return FALSE;
150 }
151 
152 /* Boolean "group-expression" AND matching, returns TRUE if the expression
153  * evaluates to TRUE.
154  */
pr_expr_eval_group_and(char ** expr)155 int pr_expr_eval_group_and(char **expr) {
156   int found;
157   char *grp;
158 
159   if (expr == NULL ||
160       *expr == NULL) {
161     errno = EINVAL;
162     return -1;
163   }
164 
165   for (; *expr; expr++) {
166     grp = *expr;
167     found = FALSE;
168 
169     if (*grp == '!') {
170       found = !found;
171       grp++;
172     }
173 
174     if (session.group &&
175         strcmp(session.group, grp) == 0) {
176       found = !found;
177 
178     } else if (session.groups) {
179       register unsigned int i = 0;
180       char **elts = session.groups->elts;
181 
182       for (i = 0; i < session.groups->nelts; i++) {
183         if (elts[i] != NULL &&
184             strcmp(elts[i], grp) == 0) {
185           found = !found;
186           break;
187         }
188       }
189     }
190 
191     if (!found)
192       return FALSE;
193   }
194 
195   return TRUE;
196 }
197 
198 /* Boolean "group-expression" OR matching, returns TRUE if the expression
199  * evaluates to TRUE.
200  */
pr_expr_eval_group_or(char ** expr)201 int pr_expr_eval_group_or(char **expr) {
202   int found;
203   char *grp;
204 
205   if (expr == NULL ||
206       *expr == NULL) {
207     errno = EINVAL;
208     return -1;
209   }
210 
211   for (; *expr; expr++) {
212     grp = *expr;
213     found = FALSE;
214 
215     if (*grp == '!') {
216       found = !found;
217       grp++;
218     }
219 
220     if (session.group &&
221         strcmp(session.group, grp) == 0) {
222       found = !found;
223 
224     } else if (session.groups) {
225       register unsigned int i = 0;
226       char **elts = session.groups->elts;
227 
228       for (i = 0; i < session.groups->nelts; i++) {
229         if (elts[i] != NULL &&
230             strcmp(elts[i], grp) == 0) {
231           found = !found;
232           break;
233         }
234       }
235     }
236 
237     if (found)
238       return TRUE;
239   }
240 
241   return FALSE;
242 }
243 
244 /* Boolean "user-expression" AND matching, returns TRUE if the expression
245  * evaluates to TRUE.
246  */
pr_expr_eval_user_and(char ** expr)247 int pr_expr_eval_user_and(char **expr) {
248   int found;
249   char *user;
250 
251   if (expr == NULL ||
252       *expr == NULL) {
253     errno = EINVAL;
254     return -1;
255   }
256 
257   for (; *expr; expr++) {
258     user = *expr;
259     found = FALSE;
260 
261     if (*user == '!') {
262       found = !found;
263       user++;
264     }
265 
266     if (session.user &&
267         strcmp(session.user, user) == 0)
268       found = !found;
269 
270     if (!found)
271       return FALSE;
272   }
273 
274   return TRUE;
275 }
276 
277 /* Boolean "user-expression" OR matching, returns TRUE if the expression
278  * evaluates to TRUE.
279  */
pr_expr_eval_user_or(char ** expr)280 int pr_expr_eval_user_or(char **expr) {
281   char *user;
282 
283   if (expr == NULL ||
284       *expr == NULL) {
285     errno = EINVAL;
286     return -1;
287   }
288 
289   for (; *expr; expr++) {
290     int found = FALSE;
291 
292     user = *expr;
293     if (*user == '!') {
294       found = !found;
295       user++;
296     }
297 
298     if (session.user != NULL &&
299         strcmp(session.user, user) == 0) {
300       found = !found;
301     }
302 
303     if (found) {
304       return TRUE;
305     }
306   }
307 
308   return FALSE;
309 }
310