1 /*
2  * Part of Very Secure FTPd
3  * Licence: GPL v2
4  * Author: Dmitriy Balashov
5  * usersip.c
6  */
7 
8 #include "usersip.h"
9 #include "tunables.h"
10 #include "str.h"
11 #include "filestr.h"
12 #include "sysutil.h"
13 #include "session.h"
14 #include "defs.h"
15 #include "logging.h"
16 #include "utility.h"
17 #include "charconv.h"
18 
19 static void parse_rules(struct mystr* p_rule_str);
20 
21 static ip_rules rules_list = 0;
22 
23 void
vsf_userip_load(const char * p_filename)24 vsf_userip_load(const char* p_filename)
25 {
26   struct mystr rules_file_str = INIT_MYSTR;
27   struct mystr rule_setting_str = INIT_MYSTR;
28   int retval;
29   unsigned int str_pos = 0;
30 
31   retval = str_fileread(&rules_file_str, p_filename, VSFTP_CONF_FILE_MAX);
32   if (vsf_sysutil_retval_is_error(retval))
33   {
34     return;
35   }
36 
37   while (str_getline(&rules_file_str, &rule_setting_str, &str_pos))
38   {
39     if (str_isempty(&rule_setting_str) ||
40         str_get_char_at(&rule_setting_str, 0) == '#')
41     {
42       continue;
43     }
44     parse_rules(&rule_setting_str);
45   }
46 
47   str_free(&rules_file_str);
48   if (!str_isempty(&rule_setting_str))
49   {
50     str_free(&rule_setting_str);
51   }
52 
53   if (rules_list) {
54     while (rules_list->prev)
55     {
56       rules_list = rules_list->prev;
57     }
58   }
59 }
60 
61 int
vsf_userip_check(const struct mystr * p_user,struct vsf_session * p_sess)62 vsf_userip_check(const struct mystr* p_user,
63                  struct vsf_session* p_sess)
64 {
65   int accept_login = (tunable_users_access_ip_deny == 1) ? 0 : 1;
66   static ip_rules rules;
67 
68   if (!rules_list)
69   {
70     return(1);
71   }
72 
73   rules = rules_list;
74 
75   do
76   {
77     if (str_equal(p_user, &rules->p_user))
78     {
79       accept_login = 0;
80       if (vsf_sysutil_sockaddr_in_mask(p_sess->p_remote_addr,
81                                        rules->remote_ip,
82                                        rules->remote_mask))
83       {
84         p_sess->remote_charset = rules->codepage;
85         return (1);
86       }
87     }
88     rules = rules->next;
89   }
90   while (rules);
91 
92   return (accept_login);
93 }
94 
95 void
vsf_userip_free()96 vsf_userip_free()
97 {
98   if (rules_list)
99   {
100     do
101     {
102       str_free(&rules_list->p_user);
103       vsf_sysutil_sockaddr_clear(&rules_list->remote_ip);
104       vsf_sysutil_sockaddr_clear(&rules_list->remote_mask);
105 
106       if (rules_list->next)
107       {
108         rules_list = rules_list->next;
109         vsf_sysutil_free (rules_list->prev);
110       } else
111       {
112         vsf_sysutil_free (rules_list);
113         rules_list = 0;
114       }
115     }
116     while (rules_list);
117   }
118 }
119 
120 static void
parse_rules(struct mystr * p_rule_str)121 parse_rules(struct mystr* p_rule_str)
122 {
123   static struct mystr s_lhs_chunk_str;
124   static struct mystr s_rhs_chunk_str;
125   static struct mystr login;
126   static struct str_locate_result locate;
127   static struct mystr s_ip;
128   static struct vsf_sysutil_sockaddr *addr_remote = 0;
129   static struct vsf_sysutil_sockaddr *addr_mask = 0;
130   int codepage = 0;
131 
132   str_replace_char(p_rule_str, '\t', ' ');
133   str_trim_char(p_rule_str, ' ');
134 
135   str_copy(&s_lhs_chunk_str, p_rule_str);
136   str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' '); // Get user login
137   str_copy(&login, &s_lhs_chunk_str);
138 
139   str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
140   str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' '); // Get user codepage
141   codepage = vsf_charconv_codepage(str_getbuf(&s_lhs_chunk_str));
142   if (codepage == 0)
143   {
144     codepage = vsf_charconv_codepage(tunable_remote_charset);
145     str_append_char(&s_lhs_chunk_str, ' ');
146     str_append_str(&s_lhs_chunk_str, &s_rhs_chunk_str);
147     str_copy(&s_rhs_chunk_str, &s_lhs_chunk_str);
148   }
149 
150   do
151   {
152     if (!addr_remote)
153     {
154       if (tunable_listen_ipv6)
155       {
156         vsf_sysutil_sockaddr_alloc_ipv6(&addr_mask);
157         vsf_sysutil_sockaddr_alloc_ipv6(&addr_remote);
158       }
159       else
160       {
161         vsf_sysutil_sockaddr_alloc_ipv4(&addr_mask);
162         vsf_sysutil_sockaddr_alloc_ipv4(&addr_remote);
163       }
164     }
165 
166     str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str);
167     str_split_char(&s_lhs_chunk_str, &s_rhs_chunk_str, ' ');
168 
169     locate = str_locate_char(&s_lhs_chunk_str, '/');
170     if (locate.found == 1)
171     {
172       str_copy(&s_ip, &s_lhs_chunk_str);
173       str_split_char(&s_ip, &s_lhs_chunk_str, '/');
174       str_append_char(&s_ip, '\0');
175       if (vsf_sysutil_inet_aton(str_getbuf(&s_ip), addr_remote) != 0)
176       {
177         if (vsf_sysutil_inet_aton(str_getbuf(&s_lhs_chunk_str), addr_mask) == 0)
178         {
179           vsf_sysutil_sockaddr_set_mask(addr_mask, str_atoi(&s_lhs_chunk_str));
180         }
181       }
182       else
183       {
184         continue;
185       }
186     }
187     else
188     {
189       str_append_char(&s_lhs_chunk_str, '\0');
190       if (vsf_sysutil_inet_aton(str_getbuf(&s_lhs_chunk_str), addr_remote) != 0)
191       {
192         vsf_sysutil_sockaddr_set_mask(addr_mask, ((tunable_listen_ipv6) ? 128 : 32));
193       }
194       else
195       {
196         continue;
197       }
198     }
199 
200     if (!rules_list)
201     {
202       rules_list = vsf_sysutil_malloc(sizeof(ip_rule));
203       vsf_sysutil_fillbuff(rules_list, sizeof(ip_rule), 0);
204     }
205     else
206     {
207       rules_list->next = vsf_sysutil_malloc(sizeof(ip_rule));
208       vsf_sysutil_fillbuff(rules_list->next, sizeof(ip_rule), 0);
209       rules_list->next->prev = rules_list;
210       rules_list = rules_list->next;
211     }
212     rules_list->remote_ip = addr_remote;
213     rules_list->remote_mask = addr_mask;
214     rules_list->codepage = codepage;
215     str_copy (&rules_list->p_user, &login);
216     addr_remote = 0;
217     addr_mask = 0;
218   }
219   while (!str_isempty(&s_rhs_chunk_str));
220 
221   if (addr_remote)
222   {
223     vsf_sysutil_sockaddr_clear(&addr_remote);
224     vsf_sysutil_sockaddr_clear(&addr_mask);
225   }
226 
227   str_free(&s_lhs_chunk_str);
228   str_free(&s_rhs_chunk_str);
229   str_free(&login);
230   str_free(&s_ip);
231 }
232 
233