]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_options.c
e39bf3f7217985cd8babe174e8379a6d370666c7
[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;
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 = strdup(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_getstrdup(config, INISEC_AFP, "loginmesg",      "");
166     options->guest          = iniparser_getstrdup(config, INISEC_AFP, "guestname",      "nobody");
167     options->passwdfile     = iniparser_getstrdup(config, INISEC_AFP, "passwdfile",     _PATH_AFPDPWFILE);
168     options->uampath        = iniparser_getstrdup(config, INISEC_AFP, "uampath",        _PATH_AFPDUAMPATH);
169     options->uamlist        = iniparser_getstrdup(config, INISEC_AFP, "uamlist",        "uams_dhx.so,uams_dhx2.so");
170     options->port           = iniparser_getstrdup(config, INISEC_AFP, "port",           "548");
171     options->signatureopt   = iniparser_getstrdup(config, INISEC_AFP, "signature",      "auto");
172     options->k5service      = iniparser_getstrdup(config, INISEC_AFP, "k5service",      NULL);
173     options->k5realm        = iniparser_getstrdup(config, INISEC_AFP, "k5realm",        NULL);
174     options->authprintdir   = iniparser_getstrdup(config, INISEC_AFP, "authprintdir",   NULL);
175     options->listen         = iniparser_getstrdup(config, INISEC_AFP, "listen",         NULL);
176     options->hostname       = iniparser_getstrdup(config, INISEC_AFP, "hostname",       NULL);
177     options->ntdomain       = iniparser_getstrdup(config, INISEC_AFP, "ntdomain",       NULL);
178     options->ntseparator    = iniparser_getstrdup(config, INISEC_AFP, "ntseparator",    NULL);
179     options->mimicmodel     = iniparser_getstrdup(config, INISEC_AFP, "mimicmodel",     NULL);
180     options->adminauthuser  = iniparser_getstrdup(config, INISEC_AFP, "adminauthuser",  NULL);
181     options->connections    = iniparser_getint   (config, INISEC_AFP, "maxcon",         200);
182     options->passwdminlen   = iniparser_getint   (config, INISEC_AFP, "passwdminlen",   0);
183     options->tickleval      = iniparser_getint   (config, INISEC_AFP, "tickleval",      30);
184     options->timeout        = iniparser_getint   (config, INISEC_AFP, "timeout",        4);
185     options->dsireadbuf     = iniparser_getint   (config, INISEC_AFP, "dsireadbuf",     12);
186     options->server_quantum = iniparser_getint   (config, INISEC_AFP, "server_quantum", DSI_SERVQUANT_DEF);
187     options->volnamelen     = iniparser_getint   (config, INISEC_AFP, "volnamelen",     80);
188     options->dircachesize   = iniparser_getint   (config, INISEC_AFP, "dircachesize",   DEFAULT_MAX_DIRCACHE_SIZE);
189     options->tcp_sndbuf     = iniparser_getint   (config, INISEC_AFP, "tcpsndbuf",      0);
190     options->tcp_rcvbuf     = iniparser_getint   (config, INISEC_AFP, "tcprcvbuf",      0);
191     options->fce_fmodwait   = iniparser_getint   (config, INISEC_AFP, "fceholdfmod",    60);
192     options->sleep          = iniparser_getint   (config, INISEC_AFP, "sleep",          10) * 60 * 2;
193     options->disconnect     = iniparser_getint   (config, INISEC_AFP, "disconnect"      24) * 60 * 2;
194
195
196     if ((p = iniparser_getstring(config, INISEC_AFP, "k5keytab", NULL))) {
197         EC_NULL_LOG( options->k5keytab = malloc(strlen(p) + 14) );
198         snprintf(options->k5keytab, strlen(p) + 14, "KRB5_KTNAME=%s", p);
199         putenv(options->k5keytab);
200     }
201
202 #ifdef ADMIN_GRP
203     if ((p = iniparser_getstring(config, INISEC_AFP, "admingroup",  NULL))) {
204          struct group *gr = getgrnam(p);
205          if (gr != NULL)
206              options->admingid = gr->gr_gid;
207     }
208 #endif /* ADMIN_GRP */
209
210     p = iniparser_getstring(config, INISEC_AFP, "cnidserver", "localhost:4700");
211     tmp = strrchr(p, ':');
212     if (tmp)
213         *t = 0;
214     options->Cnid_srv = strdup(p);
215     if (tmp)
216         options->Cnid_port = strdup(tmp + 1);
217     LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", options->Cnid_srv, options->Cnid_port);
218
219
220     if ((p = iniparser_getstring(config, INISEC_AFP, "fqdn", NULL))) {
221         /* do a little checking for the domain name. */
222         tmp = strchr(c, ':');
223         if (tmp)
224             *tmp = '\0';
225         if (gethostbyname(p)) {
226             if (tmp)
227                 *tmp = ':';
228             if ((opt = strdup(p)))
229                 options->fqdn = opt;
230         } else {
231             LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
232         }
233     }
234
235     p = iniparser_getstring(config, INISEC_AFP, "unixcodepage", "LOCALE");
236     if ((options->unixcharset = add_charset(p)) == (charset_t)-1) {
237         options->unixcharset = CH_UNIX;
238         LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p);
239     } else {
240         options->unixcodepage = strdup(p);
241     }
242         
243     p = iniparser_getstring(config, INISEC_AFP, "maccodepage", "MAC_ROMAN");
244     if ((options->maccharset = add_charset(p)) == (charset_t)-1) {
245         options->maccharset = CH_MAC;
246         LOG(log_warning, logtype_afpd, "Setting Unix codepage to '%s' failed", p);
247     } else {
248         options->maccharset = strdup(p);
249     }
250
251     if ((p = iniparser_getstring(config, INISEC_AFP, "fcelistener", NULL))) {
252                 LOG(log_note, logtype_afpd, "Adding FCE listener: %s", p);
253                 fce_add_udp_socket(p);
254     }
255     if ((p = iniparser_getstring(config, INISEC_AFP, "fcecoalesce", NULL))) {
256                 LOG(log_note, logtype_afpd, "Fce coalesce: %s", p);
257                 fce_set_coalesce(p);
258     }
259     if ((p = iniparser_getstring(config, INISEC_AFP, "fceevents", NULL))) {
260                 LOG(log_note, logtype_afpd, "Fce events: %s", p);
261                 fce_set_events(p);
262     }
263
264     /* Check for sane values */
265     if (options->tickleval <= 0)
266         options->tickleval = 30;
267     if (options->timeout <= 0)
268         options->timeout = 4;
269     if (options->sleep <= 4)
270         options->disconnected = options->sleep = 4;
271     if (options->dsireadbuf < 6)
272         options->dsireadbuf = 6;
273     if (options->volnamelen < 8)
274         options->volnamelen = 8; /* max mangled volname "???#FFFF" */
275     if (options->volnamelen > 255)
276             options->volnamelen = 255; /* AFP3 spec */
277
278     return 0;
279 }
280
281 /*
282  * Show version information about afpd.
283  * Used by "afp -v".
284  */
285 static void show_version( void )
286 {
287         int num, i;
288
289         printf( "afpd %s - Apple Filing Protocol (AFP) daemon of Netatalk\n\n", VERSION );
290
291         puts( "This program is free software; you can redistribute it and/or modify it under" );
292         puts( "the terms of the GNU General Public License as published by the Free Software" );
293         puts( "Foundation; either version 2 of the License, or (at your option) any later" );
294         puts( "version. Please see the file COPYING for further information and details.\n" );
295
296         puts( "afpd has been compiled with support for these features:\n" );
297
298         num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
299         printf( "          AFP versions:\t" );
300         for ( i = 0; i < num; i++ ) {
301                 printf( "%d.%d ", afp_versions[ i ].av_number/10, afp_versions[ i ].av_number%10);
302         }
303         puts( "" );
304
305         printf( "         CNID backends:\t" );
306 #ifdef CNID_BACKEND_CDB
307         printf( "cdb ");
308 #endif
309 #ifdef CNID_BACKEND_DB3
310         printf( "db3 " );
311 #endif
312 #ifdef CNID_BACKEND_DBD
313 #ifdef CNID_BACKEND_DBD_TXN
314         printf( "dbd-txn " );
315 #else
316         printf( "dbd " );
317 #endif
318 #endif
319 #ifdef CNID_BACKEND_HASH
320         printf( "hash " );
321 #endif
322 #ifdef CNID_BACKEND_LAST
323         printf( "last " );
324 #endif
325 #ifdef CNID_BACKEND_MTAB
326         printf( "mtab " );
327 #endif
328 #ifdef CNID_BACKEND_TDB
329         printf( "tdb " );
330 #endif
331         puts( "" );
332 }
333
334 /*
335  * Show extended version information about afpd and Netatalk.
336  * Used by "afp -V".
337  */
338 static void show_version_extended(void )
339 {
340         show_version( );
341
342         printf( "      Zeroconf support:\t" );
343 #ifdef USE_ZEROCONF
344         puts( "Yes" );
345 #else
346         puts( "No" );
347 #endif
348
349         printf( "  TCP wrappers support:\t" );
350 #ifdef TCPWRAP
351         puts( "Yes" );
352 #else
353         puts( "No" );
354 #endif
355
356         printf( "         Quota support:\t" );
357 #ifndef NO_QUOTA_SUPPORT
358         puts( "Yes" );
359 #else
360         puts( "No" );
361 #endif
362
363         printf( "   Admin group support:\t" );
364 #ifdef ADMIN_GRP
365         puts( "Yes" );
366 #else
367         puts( "No" );
368 #endif
369
370         printf( "    Valid shell checks:\t" );
371 #ifndef DISABLE_SHELLCHECK
372         puts( "Yes" );
373 #else
374         puts( "No" );
375 #endif
376
377         printf( "      cracklib support:\t" );
378 #ifdef USE_CRACKLIB
379         puts( "Yes" );
380 #else
381         puts( "No" );
382 #endif
383
384         printf( "            EA support:\t" );
385         puts( EA_MODULES );
386
387         printf( "           ACL support:\t" );
388 #ifdef HAVE_ACLS
389         puts( "Yes" );
390 #else
391         puts( "No" );
392 #endif
393
394         printf( "          LDAP support:\t" );
395 #ifdef HAVE_LDAP
396         puts( "Yes" );
397 #else
398         puts( "No" );
399 #endif
400 }
401
402 /*
403  * Display compiled-in default paths
404  */
405 static void show_paths( void )
406 {
407         printf( "             afpd.conf:\t%s\n", _PATH_AFPDCONF );
408         printf( "   AppleVolumes.system:\t%s\n", _PATH_AFPDSYSVOL );
409         printf( "  AppleVolumes.default:\t%s\n", _PATH_AFPDDEFVOL );
410         printf( "    afp_signature.conf:\t%s\n", _PATH_AFPDSIGCONF );
411         printf( "      afp_voluuid.conf:\t%s\n", _PATH_AFPDUUIDCONF );
412 #ifdef HAVE_LDAP
413         printf( "         afp_ldap.conf:\t%s\n", _PATH_ACL_LDAPCONF );
414 #else
415         printf( "         afp_ldap.conf:\tnot supported\n");
416 #endif
417         printf( "       UAM search path:\t%s\n", _PATH_AFPDUAMPATH );
418         printf( "  Server messages path:\t%s\n", SERVERTEXT);
419         printf( "              lockfile:\t%s\n", _PATH_AFPDLOCK);
420 }
421
422 /*
423  * Display usage information about afpd.
424  */
425 static void show_usage( char *name )
426 {
427         fprintf( stderr, "Usage:\t%s [-duptDTI] [-n nbpname]\n", name );
428         fprintf( stderr, "\t     [-c maxconnections] [-g guest] [-P pidfile] [-S port] [-L message]\n" );
429         fprintf( stderr, "\t     [-F configfile] [-U uams] [-m umask]\n" );
430         fprintf( stderr, "\t%s -h|-v|-V\n", name );
431 }
432
433 int afp_options_parse_cmdline(int ac, char **av)
434 {
435     char *p;
436     char *tmp;  /* Used for error checking the result of strtol */
437     int c, err = 0;
438     char buf[1024];
439
440     if (gethostname(buf, sizeof(buf)) < 0 ) {
441         perror( "gethostname" );
442         return 0;
443     }
444     if (NULL != (p = strchr(buf, '.')))
445         *p = '\0';
446     options->hostname = strdup(buf);
447
448     while (EOF != ( c = getopt( ac, av, "vVh" )) ) {
449         switch ( c ) {
450         case 'v':       /* version */
451             show_version( ); puts( "" );
452             show_paths( ); puts( "" );
453             exit( 0 );
454             break;
455         case 'V':       /* extended version */
456             show_version_extended( ); puts( "" );
457             show_paths( ); puts( "" );
458             exit( 0 );
459             break;
460         case 'h':       /* usage */
461             show_usage( p );
462             exit( 0 );
463             break;
464         default :
465             err++;
466         }
467     }
468     if ( err || optind != ac ) {
469         show_usage( p );
470         exit( 2 );
471     }
472
473     return 1;
474 }