]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_options.c
Fixes
[netatalk.git] / etc / afpd / afp_options.c
1 /*
2  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
3  * Copyright (c) 1990,1993 Regents of The University of Michigan.
4  * All Rights Reserved.  See COPYRIGHT.
5  *
6  * modified from main.c. this handles afp options.
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif /* HAVE_CONFIG_H */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <unistd.h>
18 #include <sys/param.h>
19 #include <sys/socket.h>
20 #include <atalk/logger.h>
21
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24
25 #ifdef HAVE_NETDB_H
26 #include <netdb.h>
27 #endif /* HAVE_NETDB_H */
28
29 #ifdef ADMIN_GRP
30 #include <grp.h>
31 #include <sys/types.h>
32 #endif /* ADMIN_GRP */
33
34 #include <atalk/paths.h>
35 #include <atalk/util.h>
36 #include <atalk/compat.h>
37 #include <atalk/globals.h>
38 #include <atalk/fce_api.h>
39
40 #include "status.h"
41 #include "auth.h"
42 #include "dircache.h"
43
44 #define LENGTH 512
45
46 /* get rid of any allocated afp_option buffers. */
47 void afp_options_free(struct afp_options *opt)
48 {
49         if (opt->adminauthuser)
50         free(opt->adminauthuser);
51         if (opt->configfile)
52         free(opt->configfile);
53     if (opt->fqdn)
54         free(opt->fqdn);
55     if (opt->guest)
56         free(opt->guest);
57     if (opt->ipaddr)
58         free(opt->ipaddr);
59     if (opt->k5realm)
60         free(opt->k5realm);
61     if (opt->k5keytab)
62         free(opt->k5keytab);
63     if (opt->k5service)
64         free(opt->k5service);
65     if (opt->logconfig)
66         free(opt->logconfig);
67     if (opt->loginmesg)
68         free(opt->loginmesg);
69     if (opt->maccodepage)
70         free(opt->maccodepage);
71         if (opt->mimicmodel)
72         free(opt->mimicmodel);
73     if (opt->ntdomain)
74         free(opt->ntdomain);
75     if (opt->ntseparator)
76         free(opt->ntseparator);
77     if (opt->passwdfile)
78         free(opt->passwdfile);
79     if (opt->port)
80         free(opt->port);
81     if (opt->server)
82         free(opt->server);
83     if (opt->signatureopt)
84         free(opt->signatureopt);
85     if (opt->uamlist)
86         free(opt->uamlist);
87     if (opt->uampath)
88         free(opt->uampath);
89     if (opt->unixcodepage)
90         free(opt->unixcodepage);
91 }
92
93 #define MAXVAL 1024
94 int afp_config_parse(AFPObj *AFPObj)
95 {
96     dictionary *config = AFPObj->iniconfig;
97     struct afp_options *options = &AFPObj->options;
98     int i;
99     const char *p, *tmp;
100     char val[MAXVAL];
101
102     memset(options, 0, sizeof(struct afp_options));
103     options->configfile  = strdup(_PATH_CONFDIR "afp.conf");
104     options->sigconffile = strdup(_PATH_CONFDIR "afp_signature.conf");
105     options->uuidconf    = strdup(_PATH_CONFDIR "afp_voluuid.conf");
106     options->flags |= OPTION_ACL2MACCESS | OPTION_UUID | OPTION_SERVERNOTIF;
107
108     while (EOF != (p = getopt(AFPObj->argc, AFPObj->argv, "dF:"))) {
109         switch (p) {
110         case 'd':
111             options->flags |= OPTION_DEBUG;
112             break;
113         case 'F':
114             if (options->configfile)
115                 free(options->configfile);
116             options->configfile = optarg;
117             break;
118         default :
119             break;
120         }
121     }
122
123     if ((config = iniparser_load(AFPObj->options.configfile)) == NULL)
124         return -1;
125     AFPObj->iniconfig = config;
126
127     /* [Global] */
128     options->logconfig = iniparser_getstring(config, INISEC_GLOBAL, "loglevel", "default:note");
129     options->logfile   = iniparser_getstring(config, INISEC_GLOBAL, "logfile",  NULL);
130     set_processname("afpd");
131     setuplog(logconfig, logfile);
132
133     /* [AFP] "options" options wo values */
134     p = iniparser_getstring(config, INISEC_AFP, "options", "");
135     strcpy(val, " ");
136     strlcat(val, p, MAXVAL);
137
138     if (strstr(val, " nozeroconf"))
139         options->flags |= OPTION_NOZEROCONF;
140     if (strstr(val, " icon"))
141         options->flags |= OPTION_CUSTOMICON;
142     if (strstr(val, " noicon"))
143         options->flags &= ~OPTION_CUSTOMICON;
144     if (strstr(val, " advertise_ssh"))
145         options->flags |= OPTION_ANNOUNCESSH;
146     if (strstr(val, " noacl2maccess"))
147         options->flags &= ~OPTION_ACL2MACCESS;
148     if (strstr(val, " keepsessions"))
149         options->flags |= OPTION_KEEPSESSIONS;
150     if (strstr(val, " keepsessions"))
151         options->flags |= OPTION_CLOSEVOL;
152     if (strstr(val, " client_polling"))
153         options->flags &= ~OPTION_SERVERNOTIF;
154     if (strstr(val, " nosavepassword"))
155         options->passwdbits |= PASSWD_NOSAVE;
156     if (strstr(val, " savepassword"))
157         options->passwdbits &= ~PASSWD_NOSAVE;
158     if (strstr(val, " nosetpassword"))
159         options->passwdbits &= ~PASSWD_SET;
160     if (strstr(val, " setpassword"))
161         options->passwdbits |= PASSWD_SET;
162
163     /* figure out options w values */
164
165     options->loginmesg      = iniparser_getstring(config, INISEC_AFP, "loginmesg",      "");
166     options->guest          = iniparser_getstring(config, INISEC_AFP, "guestname",      "nobody");
167     options->passwdfile     = iniparser_getstring(config, INISEC_AFP, "passwdfile",     _PATH_AFPDPWFILE);
168     options->uampath        = iniparser_getstring(config, INISEC_AFP, "uampath",        _PATH_AFPDUAMPATH);
169     options->uamlist        = iniparser_getstring(config, INISEC_AFP, "uamlist",        "uams_dhx.so,uams_dhx2.so");
170     options->port           = iniparser_getstring(config, INISEC_AFP, "port",           "548");
171     options->signatureopt   = iniparser_getstring(config, INISEC_AFP, "signature",      "auto");
172
173     options->connections    = iniparser_getint   (config, INISEC_AFP, "maxcon",         200);
174     options->passwdminlen   = iniparser_getint   (config, INISEC_AFP, "passwdminlen",   0);
175     options->tickleval      = iniparser_getint   (config, INISEC_AFP, "tickleval",      30);
176     options->timeout        = iniparser_getint   (config, INISEC_AFP, "timeout",        4);
177     options->dsireadbuf     = iniparser_getint   (config, INISEC_AFP, "dsireadbuf",     12);
178     options->server_quantum = iniparser_getint   (config, INISEC_AFP, "server_quantum", DSI_SERVQUANT_DEF);
179     options->volnamelen     = iniparser_getint   (config, INISEC_AFP, "volnamelen",     80);
180     options->dircachesize   = iniparser_getint   (config, INISEC_AFP, "dircachesize",   DEFAULT_MAX_DIRCACHE_SIZE);
181     options->tcp_sndbuf     = iniparser_getint   (config, INISEC_AFP, "tcpsndbuf",      0);
182     options->tcp_rcvbuf     = iniparser_getint   (config, INISEC_AFP, "tcprcvbuf",      0);
183     options->fce_fmodwait   = iniparser_getint   (config, INISEC_AFP, "fceholdfmod",    60);
184     options->sleep          = iniparser_getint   (config, INISEC_AFP, "sleep",          10) * 60 * 2;
185     options->disconnect     = iniparser_getint   (config, INISEC_AFP, "disconnect"      24) * 60 * 2;
186
187     options->k5service      = iniparser_getstringdup(config, INISEC_AFP, "k5service", NULL);
188     options->k5realm        = iniparser_getstringdup(config, INISEC_AFP, "k5realm", NULL);
189     options->authprintdir   = iniparser_getstringdup(config, INISEC_AFP, "authprintdir", NULL);
190     options->ipaddr         = iniparser_getstringdup(config, INISEC_AFP, "ipaddr", NULL);
191     options->hostname       = iniparser_getstringdup(config, INISEC_AFP, "hostname", NULL);
192     options->ntdomain       = iniparser_getstringdup(config, INISEC_AFP, "ntdomain", NULL);
193     options->ntseparator    = iniparser_getstringdup(config, INISEC_AFP, "ntseparator", NULL);
194     options->mimicmodel     = iniparser_getstringdup(config, INISEC_AFP, "mimicmodel", NULL);
195     options->adminauthuser  = iniparser_getstringdup(config, INISEC_AFP, "adminauthuser", NULL);
196
197     if ((p = iniparser_getstring(config, INISEC_AFP, "k5keytab", NULL))) {
198         EC_NULL_LOG( options->k5keytab = malloc(strlen(p) + 14) );
199         snprintf(options->k5keytab, strlen(p) + 14, "KRB5_KTNAME=%s", p);
200         putenv(options->k5keytab);
201     }
202
203 #ifdef ADMIN_GRP
204     if ((p = iniparser_getstring(config, INISEC_AFP, "admingroup",  NULL))) {
205          struct group *gr = getgrnam(p);
206          if (gr != NULL)
207              options->admingid = gr->gr_gid;
208     }
209 #endif /* ADMIN_GRP */
210
211     p = iniparser_getstring(config, INISEC_AFP, "cnidserver", "localhost:4700");
212     tmp = strrchr(p, ':');
213     if (tmp)
214         *t = 0;
215     options->Cnid_srv = strdup(p);
216     if (tmp)
217         options->Cnid_port = strdup(tmp + 1);
218     LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", options->Cnid_srv, options->Cnid_port);
219
220
221     if ((p = iniparser_getstring(config, INISEC_AFP, "fqdn", NULL))) {
222         /* do a little checking for the domain name. */
223         tmp = strchr(c, ':');
224         if (tmp)
225             *tmp = '\0';
226         if (gethostbyname(p)) {
227             if (tmp)
228                 *tmp = ':';
229             if ((opt = strdup(p)))
230                 options->fqdn = opt;
231         } else {
232             LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
233         }
234     }
235
236     p = iniparser_getstring(config, INISEC_AFP, "unixcodepage", "LOCALE");
237     if ((options->unixcharset = add_charset(p)) == (charset_t)-1) {
238         options->unixcharset = CH_UNIX;
239         LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p);
240     } else {
241         options->unixcodepage = strdup(p);
242     }
243         
244     p = iniparser_getstring(config, INISEC_AFP, "maccodepage", "MAC_ROMAN");
245     if ((options->maccharset = add_charset(p)) == (charset_t)-1) {
246         options->maccharset = CH_MAC;
247         LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p);
248     } else {
249         options->maccharset = strdup(p);
250     }
251
252     if ((p = iniparser_getstring(config, INISEC_AFP, "fcelistener", NULL))) {
253                 LOG(log_note, logtype_afpd, "Adding FCE listener: %s", p);
254                 fce_add_udp_socket(p);
255     }
256     if ((p = iniparser_getstring(config, INISEC_AFP, "fcecoalesce", NULL))) {
257                 LOG(log_note, logtype_afpd, "Fce coalesce: %s", p);
258                 fce_set_coalesce(p);
259     }
260     if ((p = iniparser_getstring(config, INISEC_AFP, "fceevents", NULL))) {
261                 LOG(log_note, logtype_afpd, "Fce events: %s", p);
262                 fce_set_events(p);
263     }
264
265     /* Check for sane values */
266     if (options->tickleval <= 0)
267         options->tickleval = 30;
268     if (options->timeout <= 0)
269         options->timeout = 4;
270     if (options->sleep <= 4)
271         options->disconnected = options->sleep = 4;
272     if (options->dsireadbuf < 6)
273         options->dsireadbuf = 6;
274     if (options->volnamelen < 8)
275         options->volnamelen = 8; /* max mangled volname "???#FFFF" */
276     if (options->volnamelen > 255)
277             options->volnamelen = 255; /* AFP3 spec */
278
279     return 1;
280 }
281
282 /*
283  * Show version information about afpd.
284  * Used by "afp -v".
285  */
286 static void show_version( void )
287 {
288         int num, i;
289
290         printf( "afpd %s - Apple Filing Protocol (AFP) daemon of Netatalk\n\n", VERSION );
291
292         puts( "This program is free software; you can redistribute it and/or modify it under" );
293         puts( "the terms of the GNU General Public License as published by the Free Software" );
294         puts( "Foundation; either version 2 of the License, or (at your option) any later" );
295         puts( "version. Please see the file COPYING for further information and details.\n" );
296
297         puts( "afpd has been compiled with support for these features:\n" );
298
299         num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
300         printf( "          AFP versions:\t" );
301         for ( i = 0; i < num; i++ ) {
302                 printf( "%d.%d ", afp_versions[ i ].av_number/10, afp_versions[ i ].av_number%10);
303         }
304         puts( "" );
305
306         printf( "         CNID backends:\t" );
307 #ifdef CNID_BACKEND_CDB
308         printf( "cdb ");
309 #endif
310 #ifdef CNID_BACKEND_DB3
311         printf( "db3 " );
312 #endif
313 #ifdef CNID_BACKEND_DBD
314 #ifdef CNID_BACKEND_DBD_TXN
315         printf( "dbd-txn " );
316 #else
317         printf( "dbd " );
318 #endif
319 #endif
320 #ifdef CNID_BACKEND_HASH
321         printf( "hash " );
322 #endif
323 #ifdef CNID_BACKEND_LAST
324         printf( "last " );
325 #endif
326 #ifdef CNID_BACKEND_MTAB
327         printf( "mtab " );
328 #endif
329 #ifdef CNID_BACKEND_TDB
330         printf( "tdb " );
331 #endif
332         puts( "" );
333 }
334
335 /*
336  * Show extended version information about afpd and Netatalk.
337  * Used by "afp -V".
338  */
339 static void show_version_extended(void )
340 {
341         show_version( );
342
343         printf( "      Zeroconf support:\t" );
344 #ifdef USE_ZEROCONF
345         puts( "Yes" );
346 #else
347         puts( "No" );
348 #endif
349
350         printf( "  TCP wrappers support:\t" );
351 #ifdef TCPWRAP
352         puts( "Yes" );
353 #else
354         puts( "No" );
355 #endif
356
357         printf( "         Quota support:\t" );
358 #ifndef NO_QUOTA_SUPPORT
359         puts( "Yes" );
360 #else
361         puts( "No" );
362 #endif
363
364         printf( "   Admin group support:\t" );
365 #ifdef ADMIN_GRP
366         puts( "Yes" );
367 #else
368         puts( "No" );
369 #endif
370
371         printf( "    Valid shell checks:\t" );
372 #ifndef DISABLE_SHELLCHECK
373         puts( "Yes" );
374 #else
375         puts( "No" );
376 #endif
377
378         printf( "      cracklib support:\t" );
379 #ifdef USE_CRACKLIB
380         puts( "Yes" );
381 #else
382         puts( "No" );
383 #endif
384
385         printf( "            EA support:\t" );
386         puts( EA_MODULES );
387
388         printf( "           ACL support:\t" );
389 #ifdef HAVE_ACLS
390         puts( "Yes" );
391 #else
392         puts( "No" );
393 #endif
394
395         printf( "          LDAP support:\t" );
396 #ifdef HAVE_LDAP
397         puts( "Yes" );
398 #else
399         puts( "No" );
400 #endif
401 }
402
403 /*
404  * Display compiled-in default paths
405  */
406 static void show_paths( void )
407 {
408         printf( "             afpd.conf:\t%s\n", _PATH_AFPDCONF );
409         printf( "   AppleVolumes.system:\t%s\n", _PATH_AFPDSYSVOL );
410         printf( "  AppleVolumes.default:\t%s\n", _PATH_AFPDDEFVOL );
411         printf( "    afp_signature.conf:\t%s\n", _PATH_AFPDSIGCONF );
412         printf( "      afp_voluuid.conf:\t%s\n", _PATH_AFPDUUIDCONF );
413 #ifdef HAVE_LDAP
414         printf( "         afp_ldap.conf:\t%s\n", _PATH_ACL_LDAPCONF );
415 #else
416         printf( "         afp_ldap.conf:\tnot supported\n");
417 #endif
418         printf( "       UAM search path:\t%s\n", _PATH_AFPDUAMPATH );
419         printf( "  Server messages path:\t%s\n", SERVERTEXT);
420         printf( "              lockfile:\t%s\n", _PATH_AFPDLOCK);
421 }
422
423 /*
424  * Display usage information about afpd.
425  */
426 static void show_usage( char *name )
427 {
428         fprintf( stderr, "Usage:\t%s [-duptDTI] [-n nbpname]\n", name );
429         fprintf( stderr, "\t     [-c maxconnections] [-g guest] [-P pidfile] [-S port] [-L message]\n" );
430         fprintf( stderr, "\t     [-F configfile] [-U uams] [-m umask]\n" );
431         fprintf( stderr, "\t%s -h|-v|-V\n", name );
432 }
433
434 int afp_options_parse_cmdline(int ac, char **av)
435 {
436     char *p;
437     char *tmp;  /* Used for error checking the result of strtol */
438     int c, err = 0;
439     char buf[1024];
440
441     if (gethostname(buf, sizeof(buf)) < 0 ) {
442         perror( "gethostname" );
443         return 0;
444     }
445     if (NULL != (p = strchr(buf, '.')))
446         *p = '\0';
447     options->hostname = strdup(buf);
448
449     while (EOF != ( c = getopt( ac, av, "vVh" )) ) {
450         switch ( c ) {
451         case 'v':       /* version */
452             show_version( ); puts( "" );
453             show_paths( ); puts( "" );
454             exit( 0 );
455             break;
456         case 'V':       /* extended version */
457             show_version_extended( ); puts( "" );
458             show_paths( ); puts( "" );
459             exit( 0 );
460             break;
461         case 'h':       /* usage */
462             show_usage( p );
463             exit( 0 );
464             break;
465         default :
466             err++;
467         }
468     }
469     if ( err || optind != ac ) {
470         show_usage( p );
471         exit( 2 );
472     }
473
474     return 1;
475 }