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