00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "rsync.h"
00054 #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
00055 #define strequal(a,b) (strcasecmp(a,b)==0)
00056 #define BOOLSTR(b) ((b) ? "Yes" : "No")
00057 typedef char pstring[1024];
00058 #define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
00059
00060
00061 typedef enum
00062 {
00063 P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
00064 P_STRING,P_GSTRING,P_ENUM,P_SEP
00065 } parm_type;
00066
00067 typedef enum
00068 {
00069 P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
00070 } parm_class;
00071
00072 struct enum_list {
00073 int value;
00074 char *name;
00075 };
00076
00077 struct parm_struct
00078 {
00079 char *label;
00080 parm_type type;
00081 parm_class class;
00082 void *ptr;
00083 struct enum_list *enum_list;
00084 unsigned flags;
00085 };
00086
00087 #ifndef GLOBAL_NAME
00088 #define GLOBAL_NAME "global"
00089 #endif
00090
00091
00092 #define pSERVICE(i) ServicePtrs[i]
00093 #define iSERVICE(i) (*pSERVICE(i))
00094 #define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
00095
00096
00097
00098
00099 typedef struct
00100 {
00101 char *motd_file;
00102 char *log_file;
00103 char *pid_file;
00104 int syslog_facility;
00105 char *socket_options;
00106 } global;
00107
00108 static global Globals;
00109
00110
00111
00112
00113
00114
00115 typedef struct
00116 {
00117 char *name;
00118 char *path;
00119 char *comment;
00120 char *lock_file;
00121 BOOL read_only;
00122 BOOL list;
00123 BOOL use_chroot;
00124 BOOL transfer_logging;
00125 BOOL ignore_errors;
00126 char *uid;
00127 char *gid;
00128 char *hosts_allow;
00129 char *hosts_deny;
00130 char *auth_users;
00131 char *secrets_file;
00132 BOOL strict_modes;
00133 char *exclude;
00134 char *exclude_from;
00135 char *include;
00136 char *include_from;
00137 char *log_format;
00138 char *refuse_options;
00139 char *dont_compress;
00140 int timeout;
00141 int max_connections;
00142 BOOL ignore_nonreadable;
00143 } service;
00144
00145
00146
00147 static service sDefault =
00148 {
00149 NULL,
00150 NULL,
00151 NULL,
00152 DEFAULT_LOCK_FILE,
00153 True,
00154 True,
00155 True,
00156 False,
00157 False,
00158 "nobody",
00159
00160
00161
00162
00163
00164
00165
00166
00167 "nobody",
00168
00169 NULL,
00170 NULL,
00171 NULL,
00172 NULL,
00173 True,
00174 NULL,
00175 NULL,
00176 NULL,
00177 NULL,
00178 "%o %h [%a] %m (%u) %f %l",
00179 NULL,
00180 "*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",
00181 0,
00182 0,
00183 False
00184 };
00185
00186
00187
00188
00189 static service **ServicePtrs = NULL;
00190 static int iNumServices = 0;
00191 static int iServiceIndex = 0;
00192 static BOOL bInGlobalSection = True;
00193
00194 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
00195
00196 static struct enum_list enum_facilities[] = {
00197 #ifdef LOG_AUTH
00198 { LOG_AUTH, "auth" },
00199 #endif
00200 #ifdef LOG_AUTHPRIV
00201 { LOG_AUTHPRIV, "authpriv" },
00202 #endif
00203 #ifdef LOG_CRON
00204 { LOG_CRON, "cron" },
00205 #endif
00206 #ifdef LOG_DAEMON
00207 { LOG_DAEMON, "daemon" },
00208 #endif
00209 #ifdef LOG_FTP
00210 { LOG_FTP, "ftp" },
00211 #endif
00212 #ifdef LOG_KERN
00213 { LOG_KERN, "kern" },
00214 #endif
00215 #ifdef LOG_LPR
00216 { LOG_LPR, "lpr" },
00217 #endif
00218 #ifdef LOG_MAIL
00219 { LOG_MAIL, "mail" },
00220 #endif
00221 #ifdef LOG_NEWS
00222 { LOG_NEWS, "news" },
00223 #endif
00224 #ifdef LOG_AUTH
00225 { LOG_AUTH, "security" },
00226 #endif
00227 #ifdef LOG_SYSLOG
00228 { LOG_SYSLOG, "syslog" },
00229 #endif
00230 #ifdef LOG_USER
00231 { LOG_USER, "user" },
00232 #endif
00233 #ifdef LOG_UUCP
00234 { LOG_UUCP, "uucp" },
00235 #endif
00236 #ifdef LOG_LOCAL0
00237 { LOG_LOCAL0, "local0" },
00238 #endif
00239 #ifdef LOG_LOCAL1
00240 { LOG_LOCAL1, "local1" },
00241 #endif
00242 #ifdef LOG_LOCAL2
00243 { LOG_LOCAL2, "local2" },
00244 #endif
00245 #ifdef LOG_LOCAL3
00246 { LOG_LOCAL3, "local3" },
00247 #endif
00248 #ifdef LOG_LOCAL4
00249 { LOG_LOCAL4, "local4" },
00250 #endif
00251 #ifdef LOG_LOCAL5
00252 { LOG_LOCAL5, "local5" },
00253 #endif
00254 #ifdef LOG_LOCAL6
00255 { LOG_LOCAL6, "local6" },
00256 #endif
00257 #ifdef LOG_LOCAL7
00258 { LOG_LOCAL7, "local7" },
00259 #endif
00260 { -1, NULL }};
00261
00262
00263
00264 static struct parm_struct parm_table[] =
00265 {
00266 {"motd file", P_STRING, P_GLOBAL, &Globals.motd_file, NULL, 0},
00267 {"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
00268 {"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
00269 {"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
00270 {"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
00271
00272 {"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
00273 {"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
00274 {"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
00275 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
00276 {"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
00277 {"path", P_STRING, P_LOCAL, &sDefault.path, NULL, 0},
00278 {"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
00279 {"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
00280 {"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
00281 {"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable, NULL, 0},
00282 {"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
00283 {"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
00284 {"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
00285 {"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL, 0},
00286 {"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL, 0},
00287 {"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
00288 {"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes,NULL, 0},
00289 {"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
00290 {"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
00291 {"include", P_STRING, P_LOCAL, &sDefault.include, NULL, 0},
00292 {"include from", P_STRING, P_LOCAL, &sDefault.include_from,NULL, 0},
00293 {"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
00294 {"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors,NULL,0},
00295 {"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
00296 {"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options,NULL, 0},
00297 {"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress,NULL, 0},
00298 {NULL, P_BOOL, P_NONE, NULL, NULL, 0}
00299 };
00300
00301
00302
00303
00304
00305 static void init_globals(void)
00306 {
00307 memset(&Globals, 0, sizeof(Globals));
00308 #ifdef LOG_DAEMON
00309 Globals.syslog_facility = LOG_DAEMON;
00310 #endif
00311 }
00312
00313
00314
00315
00316 static void init_locals(void)
00317 {
00318 }
00319
00320
00321
00322
00323
00324
00325
00326 #define FN_GLOBAL_STRING(fn_name,ptr) \
00327 char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
00328 #define FN_GLOBAL_BOOL(fn_name,ptr) \
00329 BOOL fn_name(void) {return(*(BOOL *)(ptr));}
00330 #define FN_GLOBAL_CHAR(fn_name,ptr) \
00331 char fn_name(void) {return(*(char *)(ptr));}
00332 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
00333 int fn_name(void) {return(*(int *)(ptr));}
00334
00335 #define FN_LOCAL_STRING(fn_name,val) \
00336 char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
00337 #define FN_LOCAL_BOOL(fn_name,val) \
00338 BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
00339 #define FN_LOCAL_CHAR(fn_name,val) \
00340 char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
00341 #define FN_LOCAL_INTEGER(fn_name,val) \
00342 int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
00343
00344
00345 FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
00346 FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
00347 FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
00348 FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
00349 FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
00350
00351 FN_LOCAL_STRING(lp_name, name)
00352 FN_LOCAL_STRING(lp_comment, comment)
00353 FN_LOCAL_STRING(lp_path, path)
00354 FN_LOCAL_STRING(lp_lock_file, lock_file)
00355 FN_LOCAL_BOOL(lp_read_only, read_only)
00356 FN_LOCAL_BOOL(lp_list, list)
00357 FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
00358 FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
00359 FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
00360 FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
00361 FN_LOCAL_STRING(lp_uid, uid)
00362 FN_LOCAL_STRING(lp_gid, gid)
00363 FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
00364 FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
00365 FN_LOCAL_STRING(lp_auth_users, auth_users)
00366 FN_LOCAL_STRING(lp_secrets_file, secrets_file)
00367 FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
00368 FN_LOCAL_STRING(lp_exclude, exclude)
00369 FN_LOCAL_STRING(lp_exclude_from, exclude_from)
00370 FN_LOCAL_STRING(lp_include, include)
00371 FN_LOCAL_STRING(lp_include_from, include_from)
00372 FN_LOCAL_STRING(lp_log_format, log_format)
00373 FN_LOCAL_STRING(lp_refuse_options, refuse_options)
00374 FN_LOCAL_STRING(lp_dont_compress, dont_compress)
00375 FN_LOCAL_INTEGER(lp_timeout, timeout)
00376 FN_LOCAL_INTEGER(lp_max_connections, max_connections)
00377
00378
00379 static int strwicmp( char *psz1, char *psz2 );
00380 static int map_parameter( char *parmname);
00381 static BOOL set_boolean( BOOL *pb, char *parmvalue );
00382 static int getservicebyname(char *name, service *pserviceDest);
00383 static void copy_service( service *pserviceDest,
00384 service *pserviceSource);
00385 static BOOL do_parameter(char *parmname, char *parmvalue);
00386 static BOOL do_section(char *sectionname);
00387
00388
00389
00390
00391
00392 static void init_service(service *pservice)
00393 {
00394 memset((char *)pservice,0,sizeof(service));
00395 copy_service(pservice,&sDefault);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 static void string_set(char **s, const char *v)
00412 {
00413 if (!v) {
00414 *s = NULL;
00415 return;
00416 }
00417 *s = strdup(v);
00418 if (!*s)
00419 exit_cleanup(RERR_MALLOC);
00420 }
00421
00422
00423
00424
00425
00426
00427 static int add_a_service(service *pservice, char *name)
00428 {
00429 int i;
00430 service tservice;
00431 int num_to_alloc = iNumServices+1;
00432
00433 tservice = *pservice;
00434
00435
00436 if (name)
00437 {
00438 i = getservicebyname(name,NULL);
00439 if (i >= 0)
00440 return(i);
00441 }
00442
00443 i = iNumServices;
00444
00445 ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
00446
00447 if (ServicePtrs)
00448 pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
00449
00450 if (!ServicePtrs || !pSERVICE(iNumServices))
00451 return(-1);
00452
00453 iNumServices++;
00454
00455 init_service(pSERVICE(i));
00456 copy_service(pSERVICE(i),&tservice);
00457 if (name)
00458 string_set(&iSERVICE(i).name,name);
00459
00460 return(i);
00461 }
00462
00463
00464
00465
00466 static int strwicmp(char *psz1, char *psz2)
00467 {
00468
00469
00470 if (psz1 == psz2)
00471 return (0);
00472 else
00473 if (psz1 == NULL)
00474 return (-1);
00475 else
00476 if (psz2 == NULL)
00477 return (1);
00478
00479
00480 while (1)
00481 {
00482 while (isspace(* (unsigned char *) psz1))
00483 psz1++;
00484 while (isspace(* (unsigned char *) psz2))
00485 psz2++;
00486 if (toupper(* (unsigned char *) psz1) != toupper(* (unsigned char *) psz2)
00487 || *psz1 == '\0' || *psz2 == '\0')
00488 break;
00489 psz1++;
00490 psz2++;
00491 }
00492 return (*psz1 - *psz2);
00493 }
00494
00495
00496
00497
00498
00499 static int map_parameter(char *parmname)
00500 {
00501 int iIndex;
00502
00503 if (*parmname == '-')
00504 return(-1);
00505
00506 for (iIndex = 0; parm_table[iIndex].label; iIndex++)
00507 if (strwicmp(parm_table[iIndex].label, parmname) == 0)
00508 return(iIndex);
00509
00510 rprintf(FERROR, "Unknown Parameter encountered: \"%s\"\n", parmname);
00511 return(-1);
00512 }
00513
00514
00515
00516
00517
00518
00519
00520 static BOOL set_boolean(BOOL *pb, char *parmvalue)
00521 {
00522 BOOL bRetval;
00523
00524 bRetval = True;
00525 if (strwicmp(parmvalue, "yes") == 0 ||
00526 strwicmp(parmvalue, "true") == 0 ||
00527 strwicmp(parmvalue, "1") == 0)
00528 *pb = True;
00529 else
00530 if (strwicmp(parmvalue, "no") == 0 ||
00531 strwicmp(parmvalue, "False") == 0 ||
00532 strwicmp(parmvalue, "0") == 0)
00533 *pb = False;
00534 else
00535 {
00536 rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
00537 parmvalue);
00538 bRetval = False;
00539 }
00540 return (bRetval);
00541 }
00542
00543
00544
00545
00546 static int getservicebyname(char *name, service *pserviceDest)
00547 {
00548 int iService;
00549
00550 for (iService = iNumServices - 1; iService >= 0; iService--)
00551 if (strwicmp(iSERVICE(iService).name, name) == 0)
00552 {
00553 if (pserviceDest != NULL)
00554 copy_service(pserviceDest, pSERVICE(iService));
00555 break;
00556 }
00557
00558 return (iService);
00559 }
00560
00561
00562
00563
00564
00565
00566
00567 static void copy_service(service *pserviceDest,
00568 service *pserviceSource)
00569 {
00570 int i;
00571
00572 for (i=0;parm_table[i].label;i++)
00573 if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
00574 void *def_ptr = parm_table[i].ptr;
00575 void *src_ptr =
00576 ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
00577 void *dest_ptr =
00578 ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
00579
00580 switch (parm_table[i].type)
00581 {
00582 case P_BOOL:
00583 case P_BOOLREV:
00584 *(BOOL *)dest_ptr = *(BOOL *)src_ptr;
00585 break;
00586
00587 case P_INTEGER:
00588 case P_ENUM:
00589 case P_OCTAL:
00590 *(int *)dest_ptr = *(int *)src_ptr;
00591 break;
00592
00593 case P_CHAR:
00594 *(char *)dest_ptr = *(char *)src_ptr;
00595 break;
00596
00597 case P_STRING:
00598 string_set(dest_ptr,*(char **)src_ptr);
00599 break;
00600
00601 default:
00602 break;
00603 }
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612 static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
00613 {
00614 int parmnum, i;
00615 void *parm_ptr=NULL;
00616 void *def_ptr=NULL;
00617
00618 parmnum = map_parameter(parmname);
00619
00620 if (parmnum < 0)
00621 {
00622 rprintf(FERROR, "IGNORING unknown parameter \"%s\"\n", parmname);
00623 return(True);
00624 }
00625
00626 def_ptr = parm_table[parmnum].ptr;
00627
00628
00629 if (snum < 0) {
00630 parm_ptr = def_ptr;
00631 } else {
00632 if (parm_table[parmnum].class == P_GLOBAL) {
00633 rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
00634 return(True);
00635 }
00636 parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
00637 }
00638
00639
00640 switch (parm_table[parmnum].type)
00641 {
00642 case P_BOOL:
00643 set_boolean(parm_ptr,parmvalue);
00644 break;
00645
00646 case P_BOOLREV:
00647 set_boolean(parm_ptr,parmvalue);
00648 *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
00649 break;
00650
00651 case P_INTEGER:
00652 *(int *)parm_ptr = atoi(parmvalue);
00653 break;
00654
00655 case P_CHAR:
00656 *(char *)parm_ptr = *parmvalue;
00657 break;
00658
00659 case P_OCTAL:
00660 sscanf(parmvalue,"%o",(int *)parm_ptr);
00661 break;
00662
00663 case P_STRING:
00664 string_set(parm_ptr,parmvalue);
00665 break;
00666
00667 case P_GSTRING:
00668 strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring));
00669 break;
00670
00671 case P_ENUM:
00672 for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
00673 if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
00674 *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
00675 break;
00676 }
00677 }
00678 if (!parm_table[parmnum].enum_list[i].name) {
00679 if (atoi(parmvalue) > 0)
00680 *(int *)parm_ptr = atoi(parmvalue);
00681 }
00682 break;
00683 case P_SEP:
00684 break;
00685 }
00686
00687 return(True);
00688 }
00689
00690
00691
00692
00693 static BOOL do_parameter(char *parmname, char *parmvalue)
00694 {
00695 return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
00696 }
00697
00698
00699
00700
00701
00702
00703 static BOOL do_section(char *sectionname)
00704 {
00705 BOOL bRetval;
00706 BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
00707 bRetval = False;
00708
00709
00710 if (bInGlobalSection && !isglobal)
00711 init_locals();
00712
00713
00714 bInGlobalSection = isglobal;
00715
00716
00717 if (bInGlobalSection)
00718 {
00719 return(True);
00720 }
00721
00722
00723 bRetval = True;
00724
00725 if (iServiceIndex >= 0)
00726 bRetval = True;
00727
00728
00729 if (bRetval)
00730 {
00731
00732
00733
00734 if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
00735 {
00736 rprintf(FERROR,"Failed to add a new service\n");
00737 return(False);
00738 }
00739 }
00740
00741 return (bRetval);
00742 }
00743
00744
00745
00746
00747
00748
00749 BOOL lp_load(char *pszFname, int globals_only)
00750 {
00751 pstring n2;
00752 BOOL bRetval;
00753
00754 bRetval = False;
00755
00756 bInGlobalSection = True;
00757
00758 init_globals();
00759
00760 pstrcpy(n2,pszFname);
00761
00762
00763 iServiceIndex = -1;
00764 bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
00765
00766 return (bRetval);
00767 }
00768
00769
00770
00771
00772
00773 int lp_numservices(void)
00774 {
00775 return(iNumServices);
00776 }
00777
00778
00779
00780
00781
00782
00783
00784 int lp_number(char *name)
00785 {
00786 int iService;
00787
00788 for (iService = iNumServices - 1; iService >= 0; iService--)
00789 if (strequal(lp_name(iService), name))
00790 break;
00791
00792 return (iService);
00793 }
00794