1 /* vi:ai:et:ts=8 sw=2
2  */
3 /*
4  * wzdftpd - a modular and cool ftp server
5  * Copyright (C) 2002-2004  Pierre Chifflier
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * As a special exemption, Pierre Chifflier
22  * and other respective copyright holders give permission to link this program
23  * with OpenSSL, and distribute the resulting executable, without including
24  * the source code for OpenSSL in the source distribution.
25  */
26 
27 #include "wzd_all.h"
28 
29 #ifndef WZD_USE_PCH
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 
37 #ifdef WIN32
38 #include <winsock2.h>
39 #else
40 #include <unistd.h>
41 
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 
47 #include <pthread.h>
48 #endif
49 
50 #include <errno.h>
51 #include <signal.h>
52 
53 #include "wzd_structs.h"
54 
55 #include "wzd_configfile.h"
56 #include "wzd_fs.h"
57 #include "wzd_group.h"
58 #include "wzd_log.h"
59 #include "wzd_misc.h"
60 #include "wzd_messages.h"
61 #include "wzd_site.h"
62 #include "wzd_site_group.h"
63 #include "wzd_user.h"
64 
65 #include "wzd_debug.h"
66 
67 #endif /* WZD_USE_PCH */
68 
69 
70 /* prototypes */
71 void do_site_help(const char *site_command, wzd_context_t * context);
72 
73 
74 
do_site_help_grpadd(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)75 int do_site_help_grpadd(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
76 {
77   send_message_with_args(501,context,"site grpadd <group> [<backend>]");
78   return 0;
79 }
80 
81 /** site grpadd: adds a new group
82  *
83  * grpadd &lt;group&gt; [&lt;backend&gt;]
84  */
do_site_grpadd(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)85 int do_site_grpadd(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
86 {
87   wzd_string_t *groupname;
88   int err;
89   wzd_user_t *me;
90   wzd_group_t *newgroup;
91   short is_gadmin;
92 
93   me = GetUserByID(context->userid);
94   is_gadmin = (me->flags && strchr(me->flags,FLAG_GADMIN)) ? 1 : 0;
95 
96   groupname = str_tok(command_line," \t\r\n");
97   if (!groupname) {
98     return do_site_help_grpadd(cname,command_line,context);
99   }
100 
101   /* Gadmin ? */
102   if (is_gadmin)
103   {
104     err = send_message_with_args(501,context,"Gadmins can't add groups!");
105     str_deallocate(groupname);
106     return 0;
107   }
108 
109   newgroup = group_create(str_tochar(groupname),context,mainConfig,&err);
110   if (newgroup == NULL) {
111     switch (err) {
112       case E_PARAM_NULL:
113       case E_PARAM_BIG:
114         err = send_message_with_args(501,context,"Invalid name or parameter");
115         break;
116       case E_PARAM_EXIST:
117         err = send_message_with_args(501,context,"A group already exists with this name");
118         break;
119       default:
120         err = send_message_with_args(501,context,"Error occured while creating group");
121         break;
122     }
123     str_deallocate(groupname);
124     return 0;
125   }
126 
127   /* add it to backend */
128   err = backend_mod_group(mainConfig->backends->filename,0,newgroup,_GROUP_CREATE);
129 
130   str_deallocate(groupname);
131 
132   if (err) {
133     err = send_message_with_args(501,context,"Could not commit new group to backend");
134     group_free(newgroup);
135   } else {
136     err = send_message_with_args(200,context,"Group added");
137     /* do not free group, it is stored in registry */
138   }
139   return 0;
140 }
141 
do_site_help_grpdel(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)142 int do_site_help_grpdel(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
143 {
144   send_message_with_args(501,context,"site grpdel <group> [<backend>]");
145   return 0;
146 }
147 
148 
149 /** site grpdel: delete group
150  *
151  * grpdel &lt;group&gt;
152  */
do_site_grpdel(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)153 int do_site_grpdel(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
154 {
155   wzd_string_t * groupname;
156   int ret;
157   wzd_user_t *me, *user;
158   short is_gadmin;
159   unsigned int gid;
160   int i;
161 /*  int users_maingroup_changed[HARD_DEF_USER_MAX];*/
162 /*  int num_users_maingroup_changed=0;*/
163 /*  int users_without_group[HARD_DEF_USER_MAX];*/
164 /*  int num_users_without_group=0;*/
165   char buffer[256];
166   int * uid_list;
167 
168   me = GetUserByID(context->userid);
169   is_gadmin = (me->flags && strchr(me->flags,FLAG_GADMIN)) ? 1 : 0;
170 
171   groupname = str_tok(command_line," \t\r\n");
172   if (!groupname) {
173     return do_site_help_grpdel(cname,command_line,context);
174   }
175   /* TODO read backend */
176 
177   /* check if group already exists */
178   if ( (gid=GetGroupIDByName(str_tochar(groupname))) == (unsigned int)-1 ) {
179     ret = send_message_with_args(501,context,"Group does not exist");
180     str_deallocate(groupname);
181     return 0;
182   }
183   str_deallocate(groupname);
184 
185   /* GAdmin ? */
186   if (is_gadmin)
187   {
188     ret = send_message_with_args(501,context,"Gadmin can't delete groups");
189     return 0;
190   }
191 
192   send_message_raw("200-\r\n",context);
193   /* iterate through user list and delete all references to group */
194   uid_list = (int*)backend_get_user(GET_USER_LIST);
195   if (uid_list) {
196     for (i=0; uid_list[i] >= 0; i++)
197     {
198       user = GetUserByID(uid_list[i]);
199       if (!user || user->username[0]=='\0') continue;
200       if (is_user_in_group(user,gid))
201       {
202         /* warn for users with no groups and / or primary group
203          * changed
204          */
205         if (user->groups[0] == gid) {
206           snprintf(buffer,sizeof(buffer),"200-WARNING %s main group is changed !\r\n",user->username);
207           send_message_raw(buffer,context);
208         }
209         group_remove_user(user,gid);
210         if (user->group_num == 0) {
211           snprintf(buffer,sizeof(buffer),"200-WARNING %s has no group now !\r\n",user->username);
212           send_message_raw(buffer,context);
213         }
214       }
215     }
216     wzd_free(uid_list);
217   } /* if (uid_list) */
218   /* TODO XXX FIXME delete users belonging only to this group ? */
219 
220   /* commit changes to backend */
221   backend_mod_group(mainConfig->backends->filename,gid,NULL,_GROUP_ALL);
222 
223   ret = send_message_raw("200 Group deleted\r\n",context);
224   return 0;
225 }
226 
do_site_help_grpren(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)227 int do_site_help_grpren(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
228 {
229   send_message_with_args(501,context,"site grpren <groupname> <newgroupname>");
230   return 0;
231 }
232 /** site grpren: rename group
233  *
234  * grpren oldname newname
235  */
do_site_grpren(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)236 int do_site_grpren(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
237 {
238   wzd_string_t * groupname, *newgroupname;
239   int ret;
240   wzd_user_t *me;
241   wzd_group_t *oldgroup;
242 /*  unsigned int ratio;*/
243   short is_gadmin;
244 
245   me = GetUserByID(context->userid);
246   is_gadmin = (me->flags && strchr(me->flags,FLAG_GADMIN)) ? 1 : 0;
247 
248   groupname = str_tok(command_line," \t\r\n");
249   if (!groupname) {
250     return do_site_help_grpren(cname,command_line,context);
251   }
252   newgroupname = str_tok(command_line," \t\r\n");
253   if (!newgroupname) {
254     str_deallocate(groupname);
255     return do_site_help_grpren(cname,command_line,context);
256   }
257 
258   /* check if group exists */
259   oldgroup = GetGroupByName(str_tochar(groupname));
260   str_deallocate(groupname);
261   if ( !oldgroup ) {
262     ret = send_message_with_args(501,context,"Group does not exist");
263     str_deallocate(newgroupname);
264     return 0;
265   }
266 
267   /* check if group exists */
268   if ( (GetGroupByName(str_tochar(newgroupname))) ) {
269     ret = send_message_with_args(501,context,"New group already exists");
270     str_deallocate(newgroupname);
271     return 0;
272   }
273 
274   if (is_gadmin)
275   {
276     ret = send_message_with_args(501,context,"GAdmins can't do that!");
277     str_deallocate(newgroupname);
278     return 0;
279   }
280 
281   strncpy(oldgroup->groupname,str_tochar(newgroupname),HARD_GROUPNAME_LENGTH-1);
282   str_deallocate(newgroupname);
283 
284   /* add it to backend */
285   ret = backend_mod_group(mainConfig->backends->filename,oldgroup->gid,oldgroup,_GROUP_GROUPNAME);
286 
287   if (ret) {
288     ret = send_message_with_args(501,context,"Problem changing value");
289   } else {
290     ret = send_message_with_args(200,context,"Group name changed");
291   }
292   return 0;
293 }
294 
do_site_ginfo(UNUSED wzd_string_t * ignored,wzd_string_t * command_line,wzd_context_t * context)295 int do_site_ginfo(UNUSED wzd_string_t *ignored, wzd_string_t *command_line, wzd_context_t * context)
296 {
297   wzd_string_t * str;
298   wzd_string_t * groupname;
299   int ret;
300   wzd_group_t * group;
301 
302   groupname = str_tok(command_line," \t\r\n");
303   if (!groupname) {
304     do_site_help("ginfo",context);
305     return 0;
306   }
307   /* check if group exists (note: we rely on cache to avoid memory leak here) */
308   group=GetGroupByName(str_tochar(groupname));
309   str_deallocate(groupname);
310   if ( !group ) {
311     ret = send_message_with_args(501,context,"Group does not exist");
312     return 0;
313   }
314 
315   str = config_get_string(mainConfig->cfg_file,"GLOBAL","sitefile_ginfo",NULL);
316   if (!str) {
317     ret = send_message_with_args(501,context,"File [GLOBAL] / sitefile_ginfo does not exist");
318     return 0;
319   }
320 
321   /* TODO XXX FIXME gadmins can see ginfo only on their primary group ? */
322   do_site_print_file(str_tochar(str),NULL,group,context);
323 
324   str_deallocate(str);
325 
326   return 0;
327 }
328 
do_site_gsinfo(UNUSED wzd_string_t * ignored,wzd_string_t * command_line,wzd_context_t * context)329 int do_site_gsinfo(UNUSED wzd_string_t *ignored, wzd_string_t *command_line, wzd_context_t * context)
330 {
331   wzd_string_t * str;
332   wzd_string_t * groupname;
333   int ret;
334   wzd_group_t * group;
335 
336   groupname = str_tok(command_line," \t\r\n");
337   if (!groupname) {
338     do_site_help("gsinfo",context);
339     return 0;
340   }
341   /* check if group exists */
342   group = GetGroupByName(str_tochar(groupname));
343   str_deallocate(groupname);
344   if ( !group ) {
345     ret = send_message_with_args(501,context,"Group does not exist");
346     return 0;
347   }
348 
349   str = config_get_string(mainConfig->cfg_file,"GLOBAL","sitefile_group",NULL);
350   if (!str) {
351     ret = send_message_with_args(501,context,"File [GLOBAL] / sitefile_group does not exist");
352     return 0;
353   }
354 
355   do_site_print_file(str_tochar(str),NULL,group,context);
356 
357   str_deallocate(str);
358 
359   return 0;
360 }
361 
do_site_help_grpaddip(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)362 int do_site_help_grpaddip(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
363 {
364   send_message_with_args(501,context,"site grpaddip <group> <ip>");
365   return 0;
366 }
367 
368 /** site grpaddip: adds an ip to a group
369  *
370  * grpaddip &lt;group&gt; &lt;ip&gt;
371  */
do_site_grpaddip(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)372 int do_site_grpaddip(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
373 {
374   wzd_string_t * groupname, *ip;
375   int ret;
376   wzd_user_t * me;
377   wzd_group_t * group;
378   short is_gadmin;
379 
380   me = GetUserByID(context->userid);
381   is_gadmin = (me->flags && strchr(me->flags,FLAG_GADMIN)) ? 1 : 0;
382 
383   groupname = str_tok(command_line," \t\r\n");
384   if (!groupname) {
385     return do_site_help_grpaddip(cname,command_line,context);
386   }
387 
388   /* check if group exists */
389   group=GetGroupByName(str_tochar(groupname));
390   str_deallocate(groupname);
391   if ( !group ) {
392     ret = send_message_with_args(501,context,"Group does not exist");
393     return 0;
394   }
395 
396   /* GAdmin ? */
397   if (is_gadmin)
398   {
399     ret = send_message_with_args(501,context,"Gadmins can't do that!");
400     return 0;
401   }
402 
403   ip = str_tok(command_line," \t\r\n");
404   if (!ip) {
405     return do_site_help_grpaddip(cname,command_line,context);
406   }
407 
408   ret = ip_inlist(group->ip_list, str_tochar(ip));
409   if (ret) {
410     ret = send_message_with_args(501,context,"IP address is already included in list");
411     str_deallocate(ip);
412     return 0;
413   }
414 
415   ret = ip_add_check(&group->ip_list, str_tochar(ip), 1 /* is_allowed */);
416   str_deallocate(ip);
417 
418   /* commit to backend */
419   backend_mod_group(mainConfig->backends->filename,group->gid,group,_GROUP_IP);
420 
421   ret = send_message_with_args(200,context,"Group IP address added");
422   return 0;
423 }
424 
do_site_help_grpdelip(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)425 int do_site_help_grpdelip(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
426 {
427   send_message_raw("501-Usage: site grpdelip <group> <ip>\r\n",context);
428   send_message_raw("501  or: site grpdelip <grp> <slot_number> (get it with site gsinfo <group>)\r\n",context);
429   return 0;
430 }
431 
432 /** site grpdelip: removes ip from group
433  *
434  * grpdelip &lt;group&gt; &lt;ip&gt;
435  *
436  * grpdelip &lt;group&gt; &lt;slot_number&gt;
437  */
do_site_grpdelip(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)438 int do_site_grpdelip(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
439 {
440   char *ptr;
441   wzd_string_t * groupname, *ip;
442   int ret;
443   wzd_user_t * me;
444   wzd_group_t * group;
445   unsigned long ul;
446   short is_gadmin;
447 
448   me = GetUserByID(context->userid);
449   is_gadmin = (me->flags && strchr(me->flags,FLAG_GADMIN)) ? 1 : 0;
450 
451   groupname = str_tok(command_line," \t\r\n");
452   if (!groupname) {
453     return do_site_help_grpdelip(cname,command_line,context);
454   }
455   /* check if group exists */
456   group=GetGroupByName(str_tochar(groupname));
457   str_deallocate(groupname);
458   if ( !group ) {
459     ret = send_message_with_args(501,context,"Group does not exist");
460     return 0;
461   }
462 
463   ip = str_tok(command_line," \t\r\n");
464   if (!ip) {
465     return do_site_help_grpdelip(cname,command_line,context);
466   }
467 
468   /* GAdmin ? */
469   if (is_gadmin)
470   {
471     ret = send_message_with_args(501,context,"Gadmins can't do that!");
472     str_deallocate(ip);
473     return 0;
474   }
475 
476   /* try to take argument as a slot number */
477   ul = strtoul(str_tochar(ip),&ptr,0);
478   if (*ptr=='\0') {
479     unsigned int i;
480     struct wzd_ip_list_t * current_ip;
481 
482     str_deallocate(ip);
483     ul--; /* to index slot number from 1 */
484     current_ip = group->ip_list;
485     for (i=0; i<ul && current_ip != NULL; i++) {
486       current_ip = current_ip->next_ip;
487     }
488     if (current_ip == NULL) {
489       char buffer[256];
490       snprintf(buffer,256,"IP slot %lu not found",ul+1);
491       ret = send_message_with_args(501,context,buffer);
492       return 0;
493     }
494     ret = ip_remove(&group->ip_list,current_ip->regexp);
495     if (ret != 0) {
496       char buffer[256];
497       snprintf(buffer,256,"error removing IP slot %lu",ul+1);
498       ret = send_message_with_args(501,context,buffer);
499       return 0;
500     }
501     backend_mod_group(mainConfig->backends->filename,group->gid,group,_GROUP_IP);
502     ret = send_message_with_args(200,context,"Group IP address removed");
503     return 0;
504   } /* if (*ptr=='\0') */
505 
506   ret = ip_remove(&group->ip_list,str_tochar(ip));
507   if (ret != 0) {
508     char buffer[256];
509     snprintf(buffer,256,"IP %s not found",str_tochar(ip));
510     ret = send_message_with_args(501,context,buffer);
511     str_deallocate(ip);
512     return 0;
513   }
514   str_deallocate(ip);
515 
516   /* commit to backend */
517   backend_mod_group(mainConfig->backends->filename,group->gid,group,_GROUP_IP);
518   ret = send_message_with_args(200,context,"Group IP address removed");
519 
520   return 0;
521 }
522 
do_site_help_grpratio(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)523 int do_site_help_grpratio(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
524 {
525   send_message_with_args(501,context,"site grpratio <group> <ratio>");
526   return 0;
527 }
528 
529 /** site grpratio: change group ratio
530  *
531  * grpratio group ratio
532  */
do_site_grpratio(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)533 int do_site_grpratio(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
534 {
535   char *ptr;
536   wzd_string_t * str_ratio, *groupname;
537   int ret;
538   wzd_user_t * me;
539   wzd_group_t * group;
540   unsigned int ratio;
541   short is_gadmin;
542 
543   me = GetUserByID(context->userid);
544   is_gadmin = (me->flags && strchr(me->flags,FLAG_GADMIN)) ? 1 : 0;
545 
546   groupname = str_tok(command_line," \t\r\n");
547   if (!groupname) {
548     return do_site_help_grpratio(cname,command_line,context);
549   }
550   /* check if group exists */
551   group=GetGroupByName(str_tochar(groupname));
552   str_deallocate(groupname);
553   if ( !group ) {
554     ret = send_message_with_args(501,context,"Group does not exist");
555     return 0;
556   }
557 
558   str_ratio = str_tok(command_line," \t\r\n");
559   if (!str_ratio) {
560     return do_site_help_grpratio(cname,command_line,context);
561   }
562 
563   ratio = strtoul(str_tochar(str_ratio),&ptr,0);
564   if (*ptr!='\0') {
565     str_deallocate(str_ratio);
566     return do_site_help_grpratio(cname,command_line,context);
567   }
568   str_deallocate(str_ratio);
569 
570   if (is_gadmin)
571   {
572     ret = send_message_with_args(501,context,"GAdmins can't do that!");
573     return 0;
574   }
575 
576   group->ratio = ratio;
577 
578   /* add it to backend */
579   ret = backend_mod_group(mainConfig->backends->filename,group->gid,group,_GROUP_RATIO);
580 
581   if (ret) {
582     ret = send_message_with_args(501,context,"Problem changing value");
583   } else {
584     ret = send_message_with_args(200,context,"Group ratio changed");
585   }
586   return 0;
587 }
588 
589 /** site grpkill: kill all connections from a group
590  *
591  * grpkill group
592  */
do_site_grpkill(UNUSED wzd_string_t * ignored,wzd_string_t * command_line,wzd_context_t * context)593 int do_site_grpkill(UNUSED wzd_string_t *ignored, wzd_string_t *command_line, wzd_context_t * context)
594 {
595   ListElmt * elmnt;
596   wzd_context_t * loop_context;
597   wzd_string_t * groupname;
598   int ret;
599   wzd_group_t * group;
600   int found=0;
601   wzd_user_t * user, * me;
602 
603   me = GetUserByID(context->userid);
604   groupname = str_tok(command_line," \t\r\n");
605   if (!groupname) {
606     do_site_help("grpkill",context);
607     return 0;
608   }
609   /* check if group exists */
610   group=GetGroupByName(str_tochar(groupname));
611   str_deallocate(groupname);
612   if ( !group ) {
613     ret = send_message_with_args(501,context,"Group does not exist");
614     return 0;
615   }
616 
617   for (elmnt=list_head(context_list); elmnt; elmnt=list_next(elmnt))
618   {
619     loop_context = list_data(elmnt);
620     if (loop_context && loop_context->magic == CONTEXT_MAGIC) {
621       user = GetUserByID(loop_context->userid);
622       if (strcmp(me->username,user->username) && is_user_in_group(user,group->gid)) {
623         found=1;
624         kill_child_new(loop_context->pid_child,context);
625       }
626     }
627   }
628 
629   if (!found) { ret = send_message_with_args(501,context,"No member found!"); }
630   else { ret = send_message_with_args(200,context,"KILL signal sent"); }
631 
632   return 0;
633 }
634 
635 
do_site_help_grpchange(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)636 int do_site_help_grpchange(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
637 {
638   send_message_raw("501-site grpchange <group> <field> <value>\r\n",context);
639   send_message_raw("field can be one of:\r\n",context);
640   send_message_raw(" name        changes the group name\r\n",context);
641   send_message_raw(" tagline     changes the group tagline\r\n",context);
642   send_message_raw(" homedir     changes group's default dir\r\n",context);
643   send_message_raw(" max_idle    changes idle time\r\n",context);
644   send_message_raw(" perms       changes default group permissions\r\n",context);
645   send_message_raw(" max_ul      changes maximum upload speed\r\n",context);
646   send_message_raw(" max_dl      changes maximum download speed\r\n",context);
647   send_message_raw(" ratio       changes group default ratio\r\n",context);
648   send_message_raw(" num_logins  changes maximum simultaneous logins allowed\r\n",context);
649 
650   send_message_raw("501 site grpchange aborted\r\n",context);
651 
652   return 0;
653 }
654 
655 /** site grpchange: change a field for a group
656  *
657  * grpchange &lt;group&gt; &lt;field&gt; &lt;value&gt;
658  */
do_site_grpchange(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)659 int do_site_grpchange(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
660 {
661   char *ptr;
662   wzd_string_t * groupname, * field, * value;
663   unsigned long mod_type, ul;
664   int ret;
665   wzd_group_t * group;
666   wzd_user_t * me;
667   gid_t gid;
668 
669   me = GetUserByID(context->userid);
670 
671   if (!command_line) {
672     return do_site_help_grpchange(cname,command_line,context);
673   }
674   groupname = str_tok(command_line," \t\r\n");
675   if (!groupname) {
676     return do_site_help_grpchange(cname,command_line,context);
677   }
678   field = str_tok(command_line," \t\r\n");
679   if (!field) {
680     str_deallocate(groupname);
681     return do_site_help_grpchange(cname,command_line,context);
682   }
683   value = str_tok(command_line,"\r\n");
684   if (!value) {
685     str_deallocate(groupname); str_deallocate(field);
686     return do_site_help_grpchange(cname,command_line,context);
687   }
688 
689   /* check if group exists */
690   if ( (group=GetGroupByName(str_tochar(groupname)))==0 ) {
691     ret = send_message_with_args(501,context,"Group does not exist");
692     str_deallocate(groupname); str_deallocate(field); str_deallocate(value);
693     return 0;
694   }
695   str_deallocate(groupname);
696   gid = group->gid;
697 
698   /* find modification type */
699   mod_type = _GROUP_NOTHING;
700 
701   /* groupname */
702   if (strcmp(str_tochar(field),"name")==0) {
703     mod_type = _GROUP_GROUPNAME;
704     strncpy(group->groupname,str_tochar(value),255);
705     /* NOTE: we do not need to iterate through users, group is referenced
706      * by id, not by name
707      */
708   }
709   /* tagline */
710   else if (strcmp(str_tochar(field),"tagline")==0) {
711     mod_type = _GROUP_TAGLINE;
712     strncpy(group->tagline,str_tochar(value),255);
713   }
714   /* homedir */
715   else if (strcmp(str_tochar(field),"homedir")==0) {
716     /* check if homedir exist */
717     {
718       fs_filestat_t s;
719       if (fs_file_stat(str_tochar(value),&s) || !S_ISDIR(s.mode)) {
720         ret = send_message_with_args(501,context,"Homedir does not exist");
721         str_deallocate(field); str_deallocate(value);
722         return 0;
723       }
724     }
725     mod_type = _GROUP_DEFAULTPATH;
726     strncpy(group->defaultpath,str_tochar(value),WZD_MAX_PATH);
727   }
728   /* max_idle */
729   else if (strcmp(str_tochar(field),"max_idle")==0) {
730     ul=strtoul(str_tochar(value),&ptr,0);
731     if (!*ptr) { mod_type = _GROUP_IDLE; group->max_idle_time = ul; }
732   }
733   /* perms */
734   else if (strcmp(str_tochar(field),"perms")==0) {
735     ul=strtoul(str_tochar(value),&ptr,0);
736     if (!*ptr) { mod_type = _GROUP_GROUPPERMS; group->groupperms = ul; }
737   }
738   /* max_ul */
739   else if (strcmp(str_tochar(field),"max_ul")==0) {
740     ul=strtoul(str_tochar(value),&ptr,0);
741     if (!*ptr) { mod_type = _GROUP_MAX_ULS; group->max_ul_speed = ul; }
742   }
743   /* max_dl */
744   else if (strcmp(str_tochar(field),"max_dl")==0) {
745     ul=strtoul(str_tochar(value),&ptr,0);
746     if (!*ptr) { mod_type = _GROUP_MAX_DLS; group->max_dl_speed = ul; }
747   }
748   /* num_logins */
749   else if (strcmp(str_tochar(field),"num_logins")==0) {
750     ul=strtoul(str_tochar(value),&ptr,0);
751     if (!*ptr) { mod_type = _GROUP_NUMLOGINS; group->num_logins = (unsigned short)ul; }
752   }
753   /* ratio */
754   else if (strcmp(str_tochar(field),"ratio")==0) {
755     ul=strtoul(str_tochar(value),&ptr,0);
756     if (!*ptr) {
757       if ((!me->flags || !strchr(me->flags,FLAG_SITEOP)) && ul==0) {
758         /* wants a leech access for group, but is not siteop */
759         ret = send_message_with_args(501,context,"Only siteops can do that");
760         str_deallocate(field); str_deallocate(value);
761         return 0;
762       }
763       mod_type = _GROUP_RATIO; group->ratio = ul;
764     }
765   }
766   else {
767     str_deallocate(field); str_deallocate(value);
768     ret = send_message_with_args(501,context,"Syntax error, unknown field");
769     return 0;
770   }
771 
772   /* commit to backend */
773   ret = backend_mod_group(mainConfig->backends->filename,gid,group,mod_type);
774 
775   str_deallocate(field); str_deallocate(value);
776 
777   if (ret)
778     ret = send_message_with_args(501,context,"Problem occured when committing");
779   else
780     ret = send_message_with_args(200,context,"Group field change successful");
781 
782   return 0;
783 }
784 
785 
do_site_help_group(UNUSED wzd_string_t * cname,UNUSED wzd_string_t * command_line,wzd_context_t * context)786 int do_site_help_group(UNUSED wzd_string_t *cname, UNUSED wzd_string_t *command_line, wzd_context_t * context)
787 {
788   send_message_raw("501-site group <action> ...\r\n",context);
789   send_message_raw("action can be one of:\r\n",context);
790   send_message_raw(" info       give group info\r\n",context);
791   send_message_raw(" add        add a new group\r\n",context);
792   send_message_raw(" delete     delete a group\r\n",context);
793   send_message_raw(" rename     rename a group\r\n",context);
794   send_message_raw(" stat       give group statistic\r\n",context);
795   send_message_raw(" addip      add an IP for group\r\n",context);
796   send_message_raw(" delip      delete an IP for group\r\n",context);
797   send_message_raw(" ratio      set group ratio\r\n",context);
798   send_message_raw(" kill       kill all group connections\r\n",context);
799   send_message_raw(" change     change group fields\r\n",context);
800   send_message_raw(" list       list all existing groups\r\n",context);
801   send_message_raw("use site <action> for specific action help\r\n",context);
802   send_message_raw("501 site group aborted\r\n",context);
803 
804   return 0;
805 }
806 
807 /* regroup all group administration in one site command */
do_site_group(wzd_string_t * cname,wzd_string_t * command_line,wzd_context_t * context)808 int do_site_group(wzd_string_t *cname, wzd_string_t *command_line, wzd_context_t * context)
809 {
810 
811   wzd_string_t * cmd;
812   int ret;
813 
814 
815   cmd = str_tok(command_line," \t\r\n");
816 
817   if( cmd == NULL ) {
818     return do_site_help_group(cname,command_line,context);
819   }
820 
821   if(strcmp("info", str_tochar(cmd)) == 0) {
822     do_site_gsinfo( cmd, command_line, context );
823   } else if(strcmp( "add", str_tochar(cmd)) == 0) {
824     do_site_grpadd( cmd, command_line, context );
825   } else if(strcmp( "delete", str_tochar(cmd)) == 0) {
826     do_site_grpdel( cmd, command_line, context );
827   } else if(strcmp( "rename", str_tochar(cmd)) == 0) {
828     do_site_grpren( cmd, command_line, context );
829   } else if(strcmp( "stat", str_tochar(cmd)) == 0) {
830     do_site_ginfo( cmd, command_line, context );
831   } else if(strcmp( "addip", str_tochar(cmd)) == 0) {
832     do_site_grpaddip( cmd, command_line, context );
833   } else if(strcmp( "delip", str_tochar(cmd)) == 0) {
834     do_site_grpdelip( cmd, command_line, context );
835   } else if(strcmp( "ratio", str_tochar(cmd)) == 0) {
836     do_site_grpratio( cmd, command_line, context );
837   } else if(strcmp( "kill", str_tochar(cmd)) == 0) {
838     do_site_grpkill( cmd, command_line, context );
839   } else if(strcmp( "change", str_tochar(cmd)) == 0) {
840     do_site_grpchange( cmd, command_line, context );
841     /** \todo FIXME implement SITE GROUP LIST */
842 /*  } else if(strcmp( "list", str_tochar(cmd)) == 0) {
843     do_site_print_file(mainConfig->site_config.file_groups,NULL,NULL,context);*/
844   } else {
845     ret = send_message_with_args(501,context,"site group action invalid");
846   }
847 
848   str_deallocate(cmd);
849 
850   return 0;
851 }
852 
853