netatalk  4.4.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
netatalk_conf.c File Reference
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <grp.h>
#include <inttypes.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pwd.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <time.h>
#include <utime.h>
#include <bstrlib.h>
#include <iniparser.h>
#include <atalk/afp.h>
#include <atalk/util.h>
#include <atalk/logger.h>
#include <atalk/ea.h>
#include <atalk/globals.h>
#include <atalk/iniparser_util.h>
#include <atalk/errchk.h>
#include <atalk/unix.h>
#include <atalk/cnid.h>
#include <atalk/dsi.h>
#include <atalk/asp.h>
#include <atalk/uuid.h>
#include <atalk/netatalk_conf.h>

Macros

#define VOLPASSLEN   8
#define UUID_PRINTABLE_STRING_LENGTH   37
#define IS_VAR(a, b)
#define EABUFSZ   4
#define MAXPRESETLEN   100
#define MAXVAL   1024

Functions

static int rewrite_vol_uuid_conf (AFPObj *obj, struct vol *Volumes)
static char * get_vol_uuid (const AFPObj *obj, const char *volname)
 Get a volume's UUID from the config file.
static int do_check_ea_support (const struct vol *vol)
 Check if the underlying filesystem supports EAs.
static void check_ea_support (struct vol *vol)
static int check_vol_acl_support (const struct vol *vol)
 Check whether a volume supports ACLs.
static char * volxlate (const AFPObj *obj, char *dest, size_t destlen, const char *src, const struct passwd *pwd, const char *path, const char *volname)
 Handle variable substitutions.
static int accessvol (const AFPObj *obj, const char *args, const char *name)
 check user access list for volume
static int hostaccessvol (const AFPObj *obj, const char *volname, const char *args)
 check host access list for volume
static const char * getoption_str (const dictionary *conf, const char *vol, const char *opt, const char *defsec, const char *defval)
 Get option string from config, use default value if not set.
static char * getoption_strdup (const dictionary *conf, const char *vol, const char *opt, const char *defsec, const char *defval)
 Get option string from config, use default value if not set.
static int getoption_bool (const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval)
 Get boolean option from config, use default value if not set.
static int getoption_int (const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval)
 Get integer option from config, use default value if not set.
static int vdgoption_bool (const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval)
 Get boolean option from volume, default section or global - use default value if not set.
static struct volcreatvol (AFPObj *obj, const struct passwd *pwd, const char *section, const char *name, const char *path_in, const char *preset)
 Create volume struct.
static int volfile_changed (AFPObj *obj)
static int vol_section (const char *sec)
static int readvolfile (AFPObj *obj, const struct passwd *pwent)
 Read volumes from iniconfig and add the volumes contained within to the global volume list.
static int setextmap (char *ext, char *type, char *creator)
static int extmap_cmp (const void *map1, const void *map2)
static void sortextmap (void)
static void free_extmap (void)
static int ext_cmp_key (const void *key, const void *obj)
struct extmapgetextmap (const char *path)
struct extmapgetdefextmap (void)
static int readextmap (const char *file)
void volume_unlink (struct vol *volume)
void volume_free (struct vol *vol)
 Free all resources allocated in a struct vol in load_volumes().
int load_charset (struct vol *vol)
int load_volumes (AFPObj *obj, lv_flags_t flags)
 Initialize volumes and load ini configfile.
void unload_volumes (AFPObj *obj)
struct volgetvolumes (void)
struct volgetvolbyvid (const uint16_t vid)
static char * getuserbypath (const char *path)
 get username by path
struct volgetvolbypath (AFPObj *obj, const char *path)
 Search volume by path, creating user home vols as necessary.
struct volgetvolbyname (const char *name)
int afp_config_parse (AFPObj *AFPObj, char *processname)
void afp_config_free (AFPObj *obj)

Variables

static int have_uservol = 0
static struct volVolumes = NULL
static uint16_t lastvid = 0
static struct extmapExtmap = NULL
static struct extmapDefextmap = NULL
static int Extmap_cnt

Macro Definition Documentation

◆ EABUFSZ

#define EABUFSZ   4

◆ IS_VAR

#define IS_VAR ( a,
b )
Value:
(strncmp((a), (b), 2) == 0)

◆ MAXPRESETLEN

#define MAXPRESETLEN   100

◆ MAXVAL

#define MAXVAL   1024

◆ UUID_PRINTABLE_STRING_LENGTH

#define UUID_PRINTABLE_STRING_LENGTH   37

◆ VOLPASSLEN

#define VOLPASSLEN   8

Function Documentation

◆ accessvol()

int accessvol ( const AFPObj * obj,
const char * args,
const char * name )
static

check user access list for volume

This function wants a string consisting of names seperated by comma or space. Names may be quoted within a pair of quotes. Groups are denoted by a leading @ symbol.

Example:

user1 user2, user3, @group1, @group2, @group3, "user name1", "@group name1"
Parameters
[in]objAFPObj containing user and group info
[in]argsaccess list string; NULL allows everybody to have access
[in]nameuser name to check
Returns
-1: no list
0: list exists, but name isn't in it
1: in list

◆ afp_config_free()

void afp_config_free ( AFPObj * obj)

get rid of any allocated afp_option buffers.

◆ afp_config_parse()

int afp_config_parse ( AFPObj * AFPObj,
char * processname )

Initialize an AFPObj and options from ini config file

◆ check_ea_support()

void check_ea_support ( struct vol * vol)
static

◆ check_vol_acl_support()

int check_vol_acl_support ( const struct vol * vol)
static

Check whether a volume supports ACLs.

Parameters
[in]volvolume
Returns
0 if not, 1 if yes

◆ creatvol()

struct vol * creatvol ( AFPObj * obj,
const struct passwd * pwd,
const char * section,
const char * name,
const char * path_in,
const char * preset )
static

Create volume struct.

Parameters
[in]objhandle
[in]pwdstruct passwd of logged in user, may be NULL in master afpd
[in]sectionvolume name wo variables expanded (exactly as in iniconfig)
[in]namevolume name
[in]path_involume path
[in]presetdefault preset, may be NULL
Returns
vol on success, NULL on error

◆ do_check_ea_support()

int do_check_ea_support ( const struct vol * vol)
static

Check if the underlying filesystem supports EAs.

If not, switch to ea=ad. As we can't check (requires write access) on ro-volumes, we assume ea=sys.

◆ ext_cmp_key()

int ext_cmp_key ( const void * key,
const void * obj )
static

◆ extmap_cmp()

int extmap_cmp ( const void * map1,
const void * map2 )
static

◆ free_extmap()

void free_extmap ( void )
static

◆ get_vol_uuid()

char * get_vol_uuid ( const AFPObj * obj,
const char * volname )
static

Get a volume's UUID from the config file.

If there is none, it is generated and stored there.

Returns
pointer to allocated storage on success, NULL on error.

◆ getdefextmap()

struct extmap * getdefextmap ( void )

◆ getextmap()

struct extmap * getextmap ( const char * path)

◆ getoption_bool()

int getoption_bool ( const dictionary * conf,
const char * vol,
const char * opt,
const char * defsec,
int defval )
static

Get boolean option from config, use default value if not set.

Parameters
[in]confconfig handle
[in]volvolume name (must be section name i.e. wo vars expanded)
[in]optoption
[in]defsecif "option" is not found in "vol", try to find it in section "defsec"
[in]defvalif neither "vol" nor "defsec" contain "opt" return "defval"
Returns
const option string from "vol" or "defsec", or "defval" if not found

◆ getoption_int()

int getoption_int ( const dictionary * conf,
const char * vol,
const char * opt,
const char * defsec,
int defval )
static

Get integer option from config, use default value if not set.

Parameters
[in]confconfig handle
[in]volvolume name (must be section name i.e. wo vars expanded)
[in]optoption
[in]defsecif "option" is not found in "vol", try to find it in section "defsec"
[in]defvalif neither "vol" nor "defsec" contain "opt" return "defval"
Returns
int option from "vol" or "defsec", or "defval" if not found

◆ getoption_str()

const char * getoption_str ( const dictionary * conf,
const char * vol,
const char * opt,
const char * defsec,
const char * defval )
static

Get option string from config, use default value if not set.

Parameters
[in]confconfig handle
[in]volvolume name (must be section name i.e. wo vars expanded)
[in]optoption
[in]defsecif "option" is not found in "vol", try to find it in section "defsec"
[in]defvalif neither "vol" nor "defsec" contain "opt" return "defval"
Returns
const option string from "vol" or "defsec", or "defval" if not found

◆ getoption_strdup()

char * getoption_strdup ( const dictionary * conf,
const char * vol,
const char * opt,
const char * defsec,
const char * defval )
static

Get option string from config, use default value if not set.

Returns a dynamically allocated string which caller must free

Parameters
[in]confconfig handle
[in]volvolume name (must be section name i.e. wo vars expanded)
[in]optoption
[in]defsecif "option" is not found in "vol", try to find it in section "defsec"
[in]defvalif neither "vol" nor "defsec" contain "opt" return "defval"
Returns
dynamically allocated option string from "vol" or "defsec", or "defval" if not found

◆ getuserbypath()

char * getuserbypath ( const char * path)
static

get username by path

getvolbypath() assumes that the user home directory has the same name as the username. If that is not true, getuserbypath() is called and tries to retrieve the username from the directory owner, checking its validity.

Parameters
[in]pathabsolute volume path
Returns
NULL if no match is found, pointer to username if successful

◆ getvolbyname()

struct vol * getvolbyname ( const char * name)

◆ getvolbypath()

struct vol * getvolbypath ( AFPObj * obj,
const char * path )

Search volume by path, creating user home vols as necessary.

Path may be absolute or relative. Ordinary volume structs are created when the ini config is initially parsed (load_volumes()), but user volumes are as load_volumes() only can create the user volume of the logged in user in an AFP session in afpd, but not when called from e.g. cnid_metad or dbd. Both cnid_metad and dbd thus need a way to lookup and create struct vols for user home by path. This is what this func does as well.

  1. Search "normal" volume list
  2. Check if theres a [Homes] section, load_volumes() remembers this for us
  3. If there is, match "path" with "basedir regex" to get the user home parent dir
  4. Built user home path by appending the basedir matched in (3) and appending the username
  5. The next path element then is the username
    • getvolbypath() assumes that the user home directory has the same name as the username. If that is not true, getuserbypath() is called and tries to retrieve the username from the directory owner, checking its validity
  6. Append [Homes]->path subdirectory if defined
  7. Create volume
Parameters
[in,out]objhandle
[in]pathpath, may be relative or absolute

◆ getvolbyvid()

struct vol * getvolbyvid ( const uint16_t vid)

◆ getvolumes()

struct vol * getvolumes ( void )

◆ hostaccessvol()

int hostaccessvol ( const AFPObj * obj,
const char * volname,
const char * args )
static

check host access list for volume

This function wants a string consisting of ip addresses or networks in CIDR notation seperated by comma or space.

Parameters
[in]objAFPObj containing client info
[in]volnamevolume name (not used)
[in]argsaccess list string; NULL allows all hosts to have access
Returns
-1: no list
0: list exists, but host isn't in it
1: host is in list

◆ load_charset()

int load_charset ( struct vol * vol)

Load charsets for a volume

◆ load_volumes()

int load_volumes ( AFPObj * obj,
lv_flags_t flags )

Initialize volumes and load ini configfile.

Parameters
[in]objhandle
[in]flagsflags controlling volume load behaviour:
  • LV_DEFAULT: load shares in a user/session context, this honors authorization
  • LV_ALL: load shares that are available in the config file
  • LV_FORCE: reload file even though the timestamp wasn't changed

◆ readextmap()

int readextmap ( const char * file)
static

◆ readvolfile()

int readvolfile ( AFPObj * obj,
const struct passwd * pwent )
static

Read volumes from iniconfig and add the volumes contained within to the global volume list.

This gets called from the forked afpd childs. The master now reads this too for Zeroconf announcements.

◆ rewrite_vol_uuid_conf()

int rewrite_vol_uuid_conf ( AFPObj * obj,
struct vol * Volumes )
static

◆ setextmap()

int setextmap ( char * ext,
char * type,
char * creator )
static

◆ sortextmap()

void sortextmap ( void )
static

◆ unload_volumes()

void unload_volumes ( AFPObj * obj)

◆ vdgoption_bool()

int vdgoption_bool ( const dictionary * conf,
const char * vol,
const char * opt,
const char * defsec,
int defval )
static

Get boolean option from volume, default section or global - use default value if not set.

Order of precedence: volume -> default section -> global -> default value

"vdg" means volume, default section or global

Parameters
[in]confconfig handle
[in]volvolume name (must be section name i.e. wo vars expanded)
[in]optoption
[in]defsecif "option" is not found in "vol", try to find it in section "defsec"
[in]defvalif neither "vol" nor "defsec" contain "opt" return "defval"
Returns
const option string from "vol" or "defsec", or "defval" if not found

◆ vol_section()

int vol_section ( const char * sec)
static

◆ volfile_changed()

int volfile_changed ( AFPObj * obj)
static

◆ volume_free()

void volume_free ( struct vol * vol)

Free all resources allocated in a struct vol in load_volumes().

Actually opening a volume (afp_openvol()) will allocate additional resources which are freed in closevol()

◆ volume_unlink()

void volume_unlink ( struct vol * volume)

Remove a volume from the linked list of volumes

◆ volxlate()

char * volxlate ( const AFPObj * obj,
char * dest,
size_t destlen,
const char * src,
const struct passwd * pwd,
const char * path,
const char * volname )
static

Handle variable substitutions.

here's what we understand:

$b -> basename of path
$c -> client ip/appletalk address
$d -> volume pathname on server
$f -> full name (whatever's in the gecos field)
$g -> group
$h -> hostname
$i -> client ip/appletalk address without port
$s -> server name (hostname if it doesn't exist)
$u -> username (guest is usually nobody)
$v -> volume name or basename if null
$$ -> $
static afpvol_t volume
Definition nad_rm.c:46
Definition include/atalk/directory.h:81
Definition cnid_metad.c:111

This get's called from readvolfile with

path = NULL, volname = NULL for xlating the volumes path
path = path, volname = NULL for xlating the volumes name
... and from volumes options parsing code when xlating e.g. dbpath with
path = path, volname = volname
static bstring dbpath
Definition etc/cnid_dbd/main.c:48

Using this information we can reject xlation of any variable depeninding on a login context which is not given in the afp master, where we must evaluate this whole stuff too for the Zeroconf announcements.

Variable Documentation

◆ Defextmap

struct extmap * Defextmap = NULL
static

◆ Extmap

struct extmap* Extmap = NULL
static

◆ Extmap_cnt

int Extmap_cnt
static

◆ have_uservol

int have_uservol = 0
static

whether there's generic user home share in config ("~" or "~/path", but not "~user")

◆ lastvid

uint16_t lastvid = 0
static

◆ Volumes

struct vol* Volumes = NULL
static