]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_options.c
New option parsing
[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 OPTIONS "dn:uc:g:P:ptS:L:F:U:hIvVm:"
45 #define LENGTH 512
46
47 /* initialize options */
48 void afp_options_init(struct afp_options *options)
49 {
50     memset(options, 0, sizeof(struct afp_options));
51
52     options->pidfile = _PATH_AFPDLOCK;
53     options->configfile = D_PATH_CONFDIR "afp.conf";
54     options->sigconffile = _PATH_AFPDSIGCONF;
55     options->uuidconf = _PATH_AFPDUUIDCONF;
56     options->server_notif = 1;
57     options->dsireadbuf = 12;
58 }
59
60 /* get rid of any allocated afp_option buffers. */
61 void afp_options_free(struct afp_options *opt)
62 {
63         if (opt->adminauthuser)
64         free(opt->adminauthuser);
65         if (opt->configfile)
66         free(opt->configfile);
67     if (opt->fqdn)
68         free(opt->fqdn);
69     if (opt->guest)
70         free(opt->guest);
71     if (opt->ipaddr)
72         free(opt->ipaddr);
73     if (opt->k5realm)
74         free(opt->k5realm);
75     if (opt->k5keytab)
76         free(opt->k5keytab);
77     if (opt->k5service)
78         free(opt->k5service);
79     if (opt->logconfig)
80         free(opt->logconfig);
81     if (opt->loginmesg)
82         free(opt->loginmesg);
83     if (opt->maccodepage)
84         free(opt->maccodepage);
85         if (opt->mimicmodel)
86         free(opt->mimicmodel);
87     if (opt->ntdomain)
88         free(opt->ntdomain);
89     if (opt->ntseparator)
90         free(opt->ntseparator);
91     if (opt->passwdfile)
92         free(opt->passwdfile);
93     if (opt->port)
94         free(opt->port);
95     if (opt->server)
96         free(opt->server);
97     if (opt->signatureopt)
98         free(opt->signatureopt);
99     if (opt->uamlist)
100         free(opt->uamlist);
101     if (opt->uampath)
102         free(opt->uampath);
103     if (opt->unixcodepage)
104         free(opt->unixcodepage);
105 }
106
107 void afp_options_duplicate(struct afp_options *options, const struct afp_options *soptions)
108 {
109     memcpy(options, soptions, sizeof(struct afp_options));
110
111     options->pidfile = NULL;
112     options->uuidconf = NULL;
113
114     options->configfile = strdup(options->configfile);
115     options->guest = strdup(options->guest);
116     options->loginmesg = strdup(options->loginmesg);
117     options->maccodepage = strdup(options->maccodepage);
118     options->passwdfile = strdup(options->passwdfile);
119     options->sigconffile = strdup(options->sigconffile);
120     options->signatureopt = strdup(options->signatureopt);
121     options->uamlist = strdup(options->uamlist);
122     options->uampath = strdup(options->uampath);
123     options->unixcodepage = strdup(options->unixcodepage);
124 }
125
126 #define MAXVAL
127 int afp_options_parse(AFPObj *AFPObj)
128 {
129     dictionary *config = AFPObj->iniconfig;
130     struct afp_options *options = &AFPObj->options;
131     int i;
132     const char *p, *tmp;
133     char val[MAXVAL];
134
135     /* [Global] */
136
137     options->logconfig      = iniparser_getstring(config, INISEC_GLOBAL, "loglevel",       "default:note");
138     options->logfile        = iniparser_getstring(config, INISEC_GLOBAL, "logfile",        NULL);
139     setuplog(logconfig, logfile);
140
141     /* [AFP] "options" options wo values */
142     options->flags |= OPTION_ACL2MACCESS | OPTION_UUID;
143
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, " nosavepassword"))
163         options->passwdbits |= PASSWD_NOSAVE;
164     if (strstr(val, " savepassword"))
165         options->passwdbits &= ~PASSWD_NOSAVE;
166     if (strstr(val, " nosetpassword"))
167         options->passwdbits &= ~PASSWD_SET;
168     if (strstr(val, " setpassword"))
169         options->passwdbits |= PASSWD_SET;
170     if (strstr(val, " client_polling"))
171         options->server_notif = 0;
172
173     /* figure out options w values */
174
175     options->loginmesg      = iniparser_getstring(config, INISEC_AFP, "loginmesg",      "");
176     options->guest          = iniparser_getstring(config, INISEC_AFP, "guestname",      "nobody");
177     options->passwdfile     = iniparser_getstring(config, INISEC_AFP, "passwdfile",     _PATH_AFPDPWFILE);
178     options->uampath        = iniparser_getstring(config, INISEC_AFP, "uampath",        _PATH_AFPDUAMPATH);
179     options->uamlist        = iniparser_getstring(config, INISEC_AFP, "uamlist",        "uams_dhx.so,uams_dhx2.so");
180     options->port           = iniparser_getstring(config, INISEC_AFP, "port",           "548");
181     options->signatureopt   = iniparser_getstring(config, INISEC_AFP, "signature",      "auto");
182
183     options->connections    = iniparser_getint   (config, INISEC_AFP, "maxcon",         200);
184     options->passwdminlen   = iniparser_getint   (config, INISEC_AFP, "passwdminlen",   0);
185     options->tickleval      = iniparser_getint   (config, INISEC_AFP, "tickleval",      30);
186     options->timeout        = iniparser_getint   (config, INISEC_AFP, "timeout",        4);
187     options->dsireadbuf     = iniparser_getint   (config, INISEC_AFP, "dsireadbuf",     12);
188     options->server_quantum = iniparser_getint   (config, INISEC_AFP, "server_quantum", DSI_SERVQUANT_DEF);
189     options->volnamelen     = iniparser_getint   (config, INISEC_AFP, "volnamelen",     80);
190     options->dircachesize   = iniparser_getint   (config, INISEC_AFP, "dircachesize",   DEFAULT_MAX_DIRCACHE_SIZE);
191     options->tcp_sndbuf     = iniparser_getint   (config, INISEC_AFP, "tcpsndbuf",      0);
192     options->tcp_rcvbuf     = iniparser_getint   (config, INISEC_AFP, "tcprcvbuf",      0);
193     options->fce_fmodwait   = iniparser_getint   (config, INISEC_AFP, "fceholdfmod",    60);
194     options->sleep          = iniparser_getint   (config, INISEC_AFP, "sleep",          10) * 60 * 2;
195     options->disconnect     = iniparser_getint   (config, INISEC_AFP, "disconnect"      24) * 60 * 2;
196
197     options->k5service      = iniparser_getstringdup(config, INISEC_AFP, "k5service", NULL);
198     options->k5realm        = iniparser_getstringdup(config, INISEC_AFP, "k5realm", NULL);
199     options->authprintdir   = iniparser_getstringdup(config, INISEC_AFP, "authprintdir", NULL);
200     options->ipaddr         = iniparser_getstringdup(config, INISEC_AFP, "ipaddr", NULL);
201     options->hostname       = iniparser_getstringdup(config, INISEC_AFP, "hostname", NULL);
202     options->ntdomain       = iniparser_getstringdup(config, INISEC_AFP, "ntdomain", NULL);
203     options->ntseparator    = iniparser_getstringdup(config, INISEC_AFP, "ntseparator", NULL);
204     options->mimicmodel     = iniparser_getstringdup(config, INISEC_AFP, "mimicmodel", NULL);
205     options->adminauthuser  = iniparser_getstringdup(config, INISEC_AFP, "adminauthuser", NULL);
206
207     if ((p = iniparser_getstring(config, INISEC_AFP, "k5keytab", NULL))) {
208         EC_NULL_LOG( options->k5keytab = malloc(strlen(p) + 14) );
209         snprintf(options->k5keytab, strlen(p) + 14, "KRB5_KTNAME=%s", p);
210         putenv(options->k5keytab);
211     }
212
213 #ifdef ADMIN_GRP
214     if ((p = iniparser_getstring(config, INISEC_AFP, "admingroup",  NULL))) {
215          struct group *gr = getgrnam(p);
216          if (gr != NULL)
217              options->admingid = gr->gr_gid;
218     }
219 #endif /* ADMIN_GRP */
220
221     p = iniparser_getstring(config, INISEC_AFP, "cnidserver", "localhost:4700");
222     tmp = strrchr(p, ':');
223     if (tmp)
224         *t = 0;
225     options->Cnid_srv = strdup(p);
226     if (tmp)
227         options->Cnid_port = strdup(tmp + 1);
228     LOG(log_debug, logtype_afpd, "CNID Server: %s:%s", options->Cnid_srv, options->Cnid_port);
229
230
231     if ((p = iniparser_getstring(config, INISEC_AFP, "fqdn", NULL))) {
232         /* do a little checking for the domain name. */
233         tmp = strchr(c, ':');
234         if (tmp)
235             *tmp = '\0';
236         if (gethostbyname(p)) {
237             if (tmp)
238                 *tmp = ':';
239             if ((opt = strdup(p)))
240                 options->fqdn = opt;
241         } else {
242             LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
243         }
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->maccharset = 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     return 1;
290 }
291
292 /*
293  * Show version information about afpd.
294  * Used by "afp -v".
295  */
296 static void show_version( void )
297 {
298         int num, i;
299
300         printf( "afpd %s - Apple Filing Protocol (AFP) daemon of Netatalk\n\n", VERSION );
301
302         puts( "This program is free software; you can redistribute it and/or modify it under" );
303         puts( "the terms of the GNU General Public License as published by the Free Software" );
304         puts( "Foundation; either version 2 of the License, or (at your option) any later" );
305         puts( "version. Please see the file COPYING for further information and details.\n" );
306
307         puts( "afpd has been compiled with support for these features:\n" );
308
309         num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
310         printf( "          AFP versions:\t" );
311         for ( i = 0; i < num; i++ ) {
312                 printf( "%d.%d ", afp_versions[ i ].av_number/10, afp_versions[ i ].av_number%10);
313         }
314         puts( "" );
315
316         printf( "         CNID backends:\t" );
317 #ifdef CNID_BACKEND_CDB
318         printf( "cdb ");
319 #endif
320 #ifdef CNID_BACKEND_DB3
321         printf( "db3 " );
322 #endif
323 #ifdef CNID_BACKEND_DBD
324 #ifdef CNID_BACKEND_DBD_TXN
325         printf( "dbd-txn " );
326 #else
327         printf( "dbd " );
328 #endif
329 #endif
330 #ifdef CNID_BACKEND_HASH
331         printf( "hash " );
332 #endif
333 #ifdef CNID_BACKEND_LAST
334         printf( "last " );
335 #endif
336 #ifdef CNID_BACKEND_MTAB
337         printf( "mtab " );
338 #endif
339 #ifdef CNID_BACKEND_TDB
340         printf( "tdb " );
341 #endif
342         puts( "" );
343 }
344
345 /*
346  * Show extended version information about afpd and Netatalk.
347  * Used by "afp -V".
348  */
349 static void show_version_extended(void )
350 {
351         show_version( );
352
353         printf( "      Zeroconf support:\t" );
354 #ifdef USE_ZEROCONF
355         puts( "Yes" );
356 #else
357         puts( "No" );
358 #endif
359
360         printf( "  TCP wrappers support:\t" );
361 #ifdef TCPWRAP
362         puts( "Yes" );
363 #else
364         puts( "No" );
365 #endif
366
367         printf( "         Quota support:\t" );
368 #ifndef NO_QUOTA_SUPPORT
369         puts( "Yes" );
370 #else
371         puts( "No" );
372 #endif
373
374         printf( "   Admin group support:\t" );
375 #ifdef ADMIN_GRP
376         puts( "Yes" );
377 #else
378         puts( "No" );
379 #endif
380
381         printf( "    Valid shell checks:\t" );
382 #ifndef DISABLE_SHELLCHECK
383         puts( "Yes" );
384 #else
385         puts( "No" );
386 #endif
387
388         printf( "      cracklib support:\t" );
389 #ifdef USE_CRACKLIB
390         puts( "Yes" );
391 #else
392         puts( "No" );
393 #endif
394
395         printf( "            EA support:\t" );
396         puts( EA_MODULES );
397
398         printf( "           ACL support:\t" );
399 #ifdef HAVE_ACLS
400         puts( "Yes" );
401 #else
402         puts( "No" );
403 #endif
404
405         printf( "          LDAP support:\t" );
406 #ifdef HAVE_LDAP
407         puts( "Yes" );
408 #else
409         puts( "No" );
410 #endif
411 }
412
413 /*
414  * Display compiled-in default paths
415  */
416 static void show_paths( void )
417 {
418         printf( "             afpd.conf:\t%s\n", _PATH_AFPDCONF );
419         printf( "   AppleVolumes.system:\t%s\n", _PATH_AFPDSYSVOL );
420         printf( "  AppleVolumes.default:\t%s\n", _PATH_AFPDDEFVOL );
421         printf( "    afp_signature.conf:\t%s\n", _PATH_AFPDSIGCONF );
422         printf( "      afp_voluuid.conf:\t%s\n", _PATH_AFPDUUIDCONF );
423 #ifdef HAVE_LDAP
424         printf( "         afp_ldap.conf:\t%s\n", _PATH_ACL_LDAPCONF );
425 #else
426         printf( "         afp_ldap.conf:\tnot supported\n");
427 #endif
428         printf( "       UAM search path:\t%s\n", _PATH_AFPDUAMPATH );
429         printf( "  Server messages path:\t%s\n", SERVERTEXT);
430         printf( "              lockfile:\t%s\n", _PATH_AFPDLOCK);
431 }
432
433 /*
434  * Display usage information about afpd.
435  */
436 static void show_usage( char *name )
437 {
438         fprintf( stderr, "Usage:\t%s [-duptDTI] [-n nbpname]\n", name );
439         fprintf( stderr, "\t     [-c maxconnections] [-g guest] [-P pidfile] [-S port] [-L message]\n" );
440         fprintf( stderr, "\t     [-F configfile] [-U uams] [-m umask]\n" );
441         fprintf( stderr, "\t%s -h|-v|-V\n", name );
442 }
443
444 int afp_options_parse_cmdline(int ac, char **av, struct afp_options *options)
445 {
446     extern char *optarg;
447     extern int optind;
448
449     char *p;
450     char *tmp;  /* Used for error checking the result of strtol */
451     int c, err = 0;
452     char buf[1024];
453
454     if (gethostname(buf, sizeof(buf)) < 0 ) {
455         perror( "gethostname" );
456         return 0;
457     }
458     if (NULL != (p = strchr(buf, '.')))
459         *p = '\0';
460     options->hostname = strdup(buf);
461
462     while (EOF != ( c = getopt( ac, av, OPTIONS )) ) {
463         switch ( c ) {
464         case 'd' :
465             options->flags |= OPTION_DEBUG;
466             break;
467         case 'F':
468             options->configfile = optarg;
469             break;
470         case 'v':       /* version */
471             show_version( ); puts( "" );
472             show_paths( ); puts( "" );
473             exit( 0 );
474             break;
475         case 'V':       /* extended version */
476             show_version_extended( ); puts( "" );
477             show_paths( ); puts( "" );
478             exit( 0 );
479             break;
480         case 'h':       /* usage */
481             show_usage( p );
482             exit( 0 );
483             break;
484         default :
485             err++;
486         }
487     }
488     if ( err || optind != ac ) {
489         show_usage( p );
490         exit( 2 );
491     }
492
493     return 1;
494 }