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