dklibs(3)

NAME
dksf - Interface to system functions

SYNOPSIS
  #include <dksf.h>

  int dksf_get_uname(char *buffer, size_t sz);
  int dksf_get_euname(char *buffer, size_t sz);
  int dksf_get_home(char *buffer, size_t sz);
  int dksf_get_ehome(char *buffer, size_t sz);
  int dksf_get_hostname(char *buffer, size_t sz);
  int dksf_get_domainname(char *buffer, size_t sz);
  int dksf_get_tempdir(char *buffer, size_t sz);
  int dksf_allowed_to_write(char *fn, int ignchk, int *rsn);
  FILE *dksf_msfo(char *fn, char *m, int ignchk, int *rsn);
  FILE *dksf_fopen(char *fn, char *mode);
  long dksf_get_maxpathlen(void);
  long dksf_get_maxfiles(void);
  int dksf_getcwd(char *buffer, size_t lgt);
  int dksf_get_executable(char *buf, size_t len, char *cd, char *pr);
  char *dksf_get_file_type_dot(char *name);
  int dksf_path_combine(char *buf, size_t len, char *p1, char *p2);
  int dksf_mkdir(char *path, int mode);
  int dksf_remove_file(char *filename);
  int dksf_remove_directory(char *filename);
  int dksf_chmod(char *path, int mode);
  int dksf_have_getuid(void);
  long dksf_getuid(void);
  int dksf_have_geteuid(void);
  long dksf_geteuid(void);
  int dksf_have_getgid(void);
  long dksf_getgid(void);
  int dksf_have_getegid(void);
  long dksf_getegid(void);
  int dksf_have_getpid(void);
  long dksf_getpid(void);
  int dksf_have_getppid(void);
  long dksf_getppid(void);
  int dksf_have_getpgrp(void);
  long dksf_getpgrp(void);
  int dksf_have_getpgid(void);
  long dksf_getpgid(long p);
  dk_stat_t *dkstat_open(char *filename);
  void dkstat_close(dk_stat_t *ptr);
  int dkstat_filetype(dk_stat_t *ptr);
  int dkstat_permissions(dk_stat_t *ptr);
  unsigned long dkstat_inode(dk_stat_t *ptr);
  unsigned long dkstat_device(dk_stat_t *ptr);
  unsigned long dkstat_rdevice(dk_stat_t *ptr);
  unsigned long dkstat_nlinks(dk_stat_t *ptr);
  dk_long_long_unsigned_t dkstat_size(dk_stat_t *ptr);
  dk_long_long_unsigned_t dkstat_size_ok(dk_stat_t *ptr, int *ok);
  long dkstat_uid(dk_stat_t *ptr);
  long dkstat_gid(dk_stat_t *ptr);
  char *dkstat_ctime(dk_stat_t *ptr);
  char *dkstat_mtime(dk_stat_t *ptr);
  char *dkstat_atime(dk_stat_t *ptr);
  dk_dir_t *dkdir_open(char *name);
  void dkdir_close(dk_dir_t *ptr);
  int dkdir_next(dk_dir_t *ptr);
  char *dkdir_get_fullname(dk_dir_t *ptr);
  char *dkdir_get_shortname(dk_dir_t *ptr);
  int dkdir_filetype(dk_stat_t *ptr);
  int dkdir_permissions(dk_stat_t *ptr);
  unsigned long dkdir_inode(dk_stat_t *ptr);
  unsigned long dkdir_device(dk_stat_t *ptr);
  unsigned long dkdir_rdevice(dk_stat_t *ptr);
  unsigned long dkdir_nlinks(dk_stat_t *ptr);
  dk_long_long_unsigned_t dkdir_size(dk_stat_t *ptr);
  dk_long_long_unsigned_t dkdir_size_ok(dk_stat_t *ptr, int *ok);
  long dkdir_uid(dk_stat_t *ptr);
  long dkdir_gid(dk_stat_t *ptr);
  char *dkdir_ctime(dk_stat_t *ptr);
  char *dkdir_mtime(dk_stat_t *ptr);
  char *dkdir_atime(dk_stat_t *ptr);
  dk_fne_t *dkfne_open(char *name, int files, int dirs);
  void dkfne_close(dk_fne_t *ptr);
  int dkfne_next(dk_fne_t *ptr);
  char *dkfne_get_fullname(dk_fne_t *ptr);
  char *dkfne_get_shortname(dk_fne_t *ptr);

DESCRIPTION

* int dksf_get_uname(char *buffer, size_t sz);
    searches for the file name of the current user (the one who started the process) and writes it to the buffer. The sz argument is the size of the buffer in bytes.

* int dksf_get_euname(char *buffer, size_t sz);
    searches for the effective user name of the current user and writes it to the buffer of sz bytes.

* int dksf_get_home(char *buffer, size_t sz);
    searches for the HOME directory of the current user and writes it to the buffer of sz bytes.

* int dksf_get_ehome(char *buffer, size_t sz);
    searches for the HOME directory of the current effective user and writes it to the buffer.

* int dksf_get_hostname(char *buffer, size_t sz);
    gets the host name of the current host and write it to the buffer.

* int dksf_get_domainname(char *buffer, size_t sz);
    gets the DNS domain name of the current host and writes it to the buffer.

* int dksf_get_tempdir(char *buffer, size_t sz);
    searches for a directory which can be used for temporary files and writes it to the buffer.

    The TMPDIR, TEMP and TMP environment variables are used in this search.

* int dksf_allowed_to_write(char *fn, int ignchk, int *rsn);
    checks whether or not writing to a file should be allowed. This is not permission checking, this function was made to avoid symlink attacks. The fn argument is the filename. ignchk contains a bit combinations for checks to skip, normally this should be 0. If writing is denied, the identifier of the failed test is written to a variable rsn points to (if rsn != NULL).

    Write access is denied if fn is a symbolic link and any of the conditions below is fullfilled:

    + DK_SF_SEC_OWNER
        The link owner is not the owner of the link destination file.

    + DK_SF_SEC_WG
        The link resides in a group writable directory.

    + DK_SF_SEC_WO
        The link resides in a world writable directory.

* FILE *dksf_msfo(char *fn, char *m, int ignchk, int *rsn);
    should be used instead of fopen() when opening files for write access. This function calls dksf_allowed_to_write() to inspect whether we should really attempt to open the file for writing. If this check is passed, the function calls fopen() to really open the file.

    The ignchk and rsn arguments are passed to dksf_allowed_to_write(), m is the mode used for fopen().

* FILE *dksf_fopen(char *fn, char *mode);
    is designed to replace fopen() calls in existing sources.

    This function calls dksf_msfo(fn, mode, 0, NULL) to open a file.

* long dksf_get_maxpathlen(void);
    returns the maximum number of bytes in a file name.

* long dksf_get_maxfiles(void);
    returns the maximum number of open files.

* int dksf_getcwd(char *buffer, size_t lgt);
    estimates the current working directory and writes the path name to the buffer.

* int dksf_get_executable(char *buf, size_t len, char *cd, char *pr);
    tries to find the full file name of the executable file currently running. Output is written to the buffer buf of length len.

    The cd argument is the current working directory, pr is the command as typed in at the prompt (argv[0]).

* char *dksf_get_file_type_dot(char *name);
    returns a pointer to the file name extension (pointer to the dot) if an extensions exists, or NULL if there is no extension.

* int dksf_path_combine(char *buf, size_t len, char *p1, char *p2);
    combines to file name paths p1 and p2 and writes the result to the pointer buf of length len.

    p1 must be an absolute path name, p2 may be absolute or relative to p1.

* int dksf_mkdir(char *path, int mode);
    creates a directory and sets permissions as specified in mode.

    Note: It is strongly recommended to use a combination of DK_PERM_... constants.

* int dksf_remove_file(char *filename);
    removes a file.

* int dksf_remove_directory(char *filename);
    removes a directory and all the contents of the directory. It is suggested to use this function with care.

* int dksf_chmod(char *path, int mode);
    changes access permissions to a file as specified in mode.

    Note: It is stronlgy recommended to use the DK_PERM_... values here.

* int dksf_have_getuid(void);
    checks whether or not the dksf_getuid() will return a usefull result (this requires a getuid() function or something equivalent).

* long dksf_getuid(void);
    returns the UID of the current user (the user which owns the process).

* int dksf_have_geteuid(void);
    checks whether or not the dksf_geteuid() function will return a usefull result.

* long dksf_geteuid(void);
    returns the effective UID.

* int dksf_have_getgid(void);
    checks whether or not dksf_getgid() will return a usefull result.

* long dksf_getgid(void);
    returns the GID of the current user.

* int dksf_have_getegid(void);
    checks whether or not dksf_getegid() will return a usefull result.

* long dksf_getegid(void);
    returns the effective GID.

* int dksf_have_getpid(void);
    checks whether or not dksf_getpid() will return a usefull result.

* long dksf_getpid(void);
    returns the PID of the current process.

* int dksf_have_getppid(void);
    checks whether or not dksf_getppid() will return a usefull result.

* long dksf_getppid(void);
    returns the PID of the parent process.

* int dksf_have_getpgrp(void);
    checks whether or not dksf_getpgrp() will return a usefull result.

* long dksf_getpgrp(void);
    returns the process group ID of the current process.

* int dksf_have_getpgid(void);
    checks whether or not dksf_getpgid() will return a usefull result.

* long dksf_getpgid(long p);
    returns the process group ID of the process given by PID p.

* Obtaining information about files
    To obtain information about a file the dkstat_open() function dynamically creates a dk_stat_t and fills it with data.

    After usage the dk_stat_t must be released using the dkstat_close() function.

    The other functions are used to retrieve information from the dk_stat_t.

    + dk_stat_t *dkstat_open(char *filename);
        allocates memory for a dk_stat_t and writes information about the file given by filename into it.

        The dkstat_close() function should be used to release the dk_stat_t and the ressources assigned to it.

    + void dkstat_close(dk_stat_t *ptr);
        releases a dk_stat_t allocated by dkstat_open().

    + int dkstat_filetype(dk_stat_t *ptr);
        returns the file type as a combination of DK_FT_... constants.

    + int dkstat_permissions(dk_stat_t *ptr);
        returns the permissions to the file as a combination of DK_PERM_... values.

    + unsigned long dkstat_inode(dk_stat_t *ptr);
        returns the inode number of the file.

    + unsigned long dkstat_device(dk_stat_t *ptr);
        returns the device number of the file.

    + unsigned long dkstat_rdevice(dk_stat_t *ptr);
        returns the relative device number of the file.

    + unsigned long dkstat_nlinks(dk_stat_t *ptr);
        returns the number of links.

    + dk_long_long_unsigned_t dkstat_size(dk_stat_t *ptr);
        returns the file size.

    + dk_long_long_unsigned_t dkstat_size_ok(dk_stat_t *ptr, int *ok);
        returns the file size. The ok parameter is a pointer to an int variable. If an error occurs during file size conversion, this variable is set to 1. Otherwise the variable is unchanged.

    + long dkstat_uid(dk_stat_t *ptr);
        returns the file owner's UID.

    + long dkstat_gid(dk_stat_t *ptr);
        returns the file group's GID.

    + char *dkstat_ctime(dk_stat_t *ptr);
        returns a pointer to a string containing the file creation time as i.e. "2003/11/25 20:44:23".

        The string is stored inside the dk_stat_t, after releasing the dk_stat_t it is no longer accessable.

    + char *dkstat_mtime(dk_stat_t *ptr);
        returns a pointer to a string containing the last modification time stamp.

    + char *dkstat_atime(dk_stat_t *ptr);
        returns a pointer to a string containing the last access timestamp.

* Directory traversal
    To traverse a directory, a dk_dir_t structure is created by calling dkdir_open(), the directory name is given as name parameter. After usage this structure and the assigned ressources must be released using the dkdir_close() function.

    Traversal is done by calling dkdir_next(). This function indicates success if there was yet another directory entry found. When doing recursive traversal take care of the "." and ".." entries.

    If an entry was found, the functions dkdir_get_fullname(), dkdir_get_shortname(), dkdir_filetype(), dkdir_permissions(), dkdir_inode(), dkdir_device(), dkdir_rdevice(), dkdir_nlinks(), dkdir_size(), dkdir_size_ok(), dkdir_uid(), dkdir_gid(), dkdir_ctime(), dkdir_mtime() and dkdir_atime() can be used to obtain information about the entry.

    + dk_dir_t *dkdir_open(char *name);
        creates a dk_dir_t structure.

    + void dkdir_close(dk_dir_t *ptr);
        releases a dk_dir_t structure.

    + int dkdir_next(dk_dir_t *ptr);
        tries to find a directory entry.

    + char *dkdir_get_fullname(dk_dir_t *ptr);
        returns the full name (complete path name) of the directory entry.

        The buffer is overwritten by the next dkdir_next() call and released by dkdir_close(). In both cases the pointer can not longer be used.

    + char *dkdir_get_shortname(dk_dir_t *ptr);
        returns the short name (without the leading directory path) of the directory entry.

        The buffer is overwritten by the next dkdir_next() call and released by dkdir_close(). In both cases the pointer can not longer be used.

    + int dkdir_filetype(dk_stat_t *ptr);
        returns the file type as combination of DK_FT_... values.

    + int dkdir_permissions(dk_stat_t *ptr);
        returns the file permissions as a combination of DK_PERM_... values.

    + unsigned long dkdir_inode(dk_stat_t *ptr);
        returns the inode number.

    + unsigned long dkdir_device(dk_stat_t *ptr);
        returns the device number.

    + unsigned long dkdir_rdevice(dk_stat_t *ptr);
        returns the relative device number.

    + unsigned long dkdir_nlinks(dk_stat_t *ptr);
        returns the number of links.

    + dk_long_long_unsigned_t dkdir_size(dk_stat_t *ptr);
        returns the file size.

    + dk_long_long_unsigned_t dkdir_size_ok(dk_stat_t *ptr, int *ok);
        returns the file size. The ok parameter is a pointer to an int variable. If size conversion to the long long type fails, this variable is set to 1, otherwise it is unchanged.

    + long dkdir_uid(dk_stat_t *ptr);
        returns the file owner's UID.

    + long dkdir_gid(dk_stat_t *ptr);
        returns the file group's GID.

    + char *dkdir_ctime(dk_stat_t *ptr);
        returns a pointer to a buffer containing the file creation time stamp as text.

        The buffer is overwritten by the next dkdir_next() call and released by dkdir_close(). In both cases the pointer can not longer be used.

    + char *dkdir_mtime(dk_stat_t *ptr);
        returns a pointer to a buffer containing the file modification timestamp as text.

        The buffer is overwritten by the next dkdir_next() call and released by dkdir_close(). In both cases the pointer can not longer be used.

    + char *dkdir_atime(dk_stat_t *ptr);
        returns a pointer to a buffer containing the file access timestamp as text.

        The buffer is overwritten by the next dkdir_next() call and released by dkdir_close(). In both cases the pointer can not longer be used.

* Expanding wildcards in file names
    This expansion process is sometimes referred to as "globbing".

    Some command interpreters (typically invoked by the commands "COMMAND.COM" or "CMD.EXE") do not expand "?" and "*" wildcards in file names as real shells do. They leave it up to each program to deal with it.

    To search for matching files and/or directories the dkfne_open() function creates a dk_fne_t structure for a name containing wildcards. The files and dirs parameter are simple flags indicating by non-zero values that names for files and/or directories are acceptable. In short: if you want to have names of regular files only, set the dirs parameter to 0. The dkfne_close() function must be used to release the dk_fne_t structure and the ressources assigned to it.

    Finding names matching the pattern is done using the dkfne_next() function. This function indicates success if there is yet another directory entry matching the pattern and the files/dirs criteria. In this case the dkfne_get_fullname() and/or dkfne_get_shortname() functions can be used to retrieve the directory entry name.

    + dk_fne_t *dkfne_open(char *name, int files, int dirs);
        creates a dk_fne_t structure and sets it up for the pattern specified in name and the search criteria given in files and dirs. The dkfne_close() function must be used to release the structure and assigned ressources when the structure is no longer needed.

    + void dkfne_close(dk_fne_t *ptr);
        releases the dk_fne_t structure and assigned ressources.

    + int dkfne_next(dk_fne_t *ptr);
        checks whether or not there is yet another directory entry available matching the pattern and search criteria specified as arguments to dkfne_opne().

    + char *dkfne_get_fullname(dk_fne_t *ptr);
        retrieves a "full" path name (which may be a relative name if the name argument was a relative path name).

    + char *dkfne_get_shortname(dk_fne_t *ptr);
        retrieves the short name.

RETURN VALUE
All functions returning an int value return a non-zero value on success and zero on error unless stated otherwise.

Functions returning pointers return a valid pointer on success, NULL on error.

SECURITY ISSUES
You should not use the following functions in SUID/SGID programs:

dksf_get_uname()
dksf_get_euname()
dksf_get_home()
dksf_get_ehome()
dksf_get_hostname()
dksf_get_domainname()
dksf_get_tempdir()
dksf_get_executable()

These functions use environment variables and/or retrieve data from user writable parts in the Windows registry. If they fail to retrieve settings in a traditional way the provide fallback data. I.e. if dksf_get_tempdir() can not find a directory for temporary files but there is information about the user's home directory available, the home directory is used for temporary files too (because we hope it is writable for the current user).

This behaviour is ok for "normal" programs because it allows to recover from configuration problems but completely inacceptable for SUID/SGID programs. When using dksf_getpid(), dksf_getppid(), dksf_getuid(), dksf_geteuid(), dksf_getgid(), dksf_getegid(), dksf_getpgrp() or dksf_getpgid() it is recommended to use dksf_have_...() to check whether or not the functions return usefull values.

SEE ALSO
The dksfc.h header files contains definitions for the DK_FT_... and DK_PERM_... values.

AUTHOR
Dirk Krause

COPYRIGHT AND LICENSE
Copyright (c) 2001-2008, Dirk Krause All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above
   copyright notice, this list of conditions and the
   following disclaimer.

 * Redistributions in binary form must reproduce the above
   copyright notice, this list of conditions and the following
   disclaimer in the documentation and/or other materials
   provided with the distribution.

 * Neither the name of the Dirk Krause nor the names of
   contributors may be used to endorse or promote products
   derived from this software without specific prior written
   permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.