File Safety Functions
Functions for running file safety checks are implemented in libmailutils. The corresponding prototypes and constants are declared in the header mailutils/util.h[1].
mu_file_safety_check
int mu_file_safety_check (const char *filename,
int mode,
uid_t uid,
mu_list_t idlist);
The function mu_file_safety_check checks whether the file filename satisfies safety checks described by the mode and uid arguments.
Its arguments are:
- filename
- Name of the file to check.
- mode
- A bitmap specifying the checks to perform. It can be constructed as a bitwise OR of one or more of the following flags, corresponding to the main safety checks:
- MU_FILE_SAFETY_OWNER_MISMATCH
- Check whether the file owner UID equals to the uid argument.
- MU_FILE_SAFETY_WORLD_WRITABLE
- Fail if the file is world writable (awrfil)
- MU_FILE_SAFETY_GROUP_WRITABLE
- Fail if the file is group writable (gwrfil)
- MU_FILE_SAFETY_LINKED_WRDIR
- Fail if the file is a symbolic link located in a (world- or group-) writable directory (linkwrdir)
- MU_FILE_SAFETY_DIR_IWGRP
- Fail if the file is located in a group-writable directory (gwrdir)
- MU_FILE_SAFETY_DIR_IWOTH
- Fail if the file is located in a world-writable directory (awrdir)
- MU_FILE_SAFETY_WORLD_READABLE
- Fail if the file is world readable (awrfil)
- MU_FILE_SAFETY_GROUP_READABLE
- Fail if the file is group readable (grdfil)
- Additionally, the following two defines are provided:
- MU_FILE_SAFETY_ALL
- All the above checks
- MU_FILE_SAFETY_NONE
- No checks
- uid
- UID the file should be owned by, if the MU_FILE_SAFETY_OWNER_MISMATCH mode is specified.
- idlist
- A list used to avoid checking the same file twice. It is useful if mu_file_safety_check is to be called several times. At the first call to the function, this argument should contain a newly created list. The function uses this list to keep record of the device and inode numbers of processed files. If mu_file_safety_check determines that the file it is about to check is already entered in this list, it will immediately return MU_ERR_EXISTS.
- If this is not needed, this argument should be NULL.
The mu_file_safety_check returns 0 if the file passes all checks, or one of the following error codes otherwise:
- MU_ERR_PERM_OWNER_MISMATCH
- File owner does not match the requested UID.
- MU_ERR_PERM_WORLD_WRITABLE
- File is world writable
- MU_ERR_PERM_GROUP_WRITABLE
- File is group writable
- MU_ERR_PERM_LINKED_WRDIR
- Linked file in a writable directory
- MU_ERR_PERM_DIR_IWGRP
- File resides in group writable directory
- MU_ERR_PERM_DIR_IWOTH
- File resides in world writable directory
- MU_ERR_PERM_WORLD_READABLE
- File is world readable
- MU_ERR_PERM_GROUP_READABLE
- File is group readable
- MU_ERR_EXISTS
- The file has already been checked before (see the description of the idlist argument, above).
mu_file_safety_name_to_code
int mu_file_safety_name_to_code (const char *name, int *pcode);
This function converts the symbolic safety check name name to the corresponding MU_FILE_SAFETY constant.
If the conversion succeeds, the function stores the result in the memory location pointed to by the pcode argument and returns 0. If name does not match any safety check name, the function returns MU_ERR_NOENT.
mu_file_safety_name_to_error
int mu_file_safety_name_to_error (const char *name, int *pcode);
This function converts the symbolic safety check name name to the corresponding MU_ERR_PERM error code.
If the conversion succeeds, the function stores the result in the memory location pointed to by the pcode argument and returns 0. If name does not match any safety check name, the function returns MU_ERR_NOENT.
Safety Checks, Modes and Error Codes
The following table summarizes the available safety checks and their corresponding mode and error codes:
Check name | Mode | Error code |
---|---|---|
N/A | MU_FILE_SAFETY_OWNER_MISMATCH | MU_ERR_PERM_OWNER_MISMATCH |
awrfil | MU_FILE_SAFETY_WORLD_WRITABLE | MU_ERR_PERM_WORLD_WRITABLE |
gwrfil | MU_FILE_SAFETY_GROUP_WRITABLE | MU_ERR_PERM_GROUP_WRITABLE |
linkwrdir | MU_FILE_SAFETY_LINKED_WRDIR | MU_ERR_PERM_LINKED_WRDIR |
awrdir | MU_FILE_SAFETY_DIR_IWGRP | MU_ERR_PERM_DIR_IWGRP |
gwrdir | MU_FILE_SAFETY_DIR_IWOTH | MU_ERR_PERM_DIR_IWOTH |
ardfil | MU_FILE_SAFETY_WORLD_READABLE | MU_ERR_PERM_WORLD_READABLE |
grdfil | MU_FILE_SAFETY_GROUP_READABLE | MU_ERR_PERM_GROUP_READABLE |
Example
The following example implements a utility which applies the requested safety checks to a set of files. Both check modes and file names are supplied in the command line and can be interspersed. Each check mode begins with a plus sign, in which case the corresponding check is enabled, or with a minus sign in which case it is disabled.
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <mailutils/types.h>
5#include <mailutils/error.h>
6#include <mailutils/errno.h>
7#include <mailutils/util.h>
8
9int
10main (int argc, char **argv)
11{
12 int i;
13 int mode = MU_FILE_SAFETY_OWNER_MISMATCH, rc, m;
14 mu_list_t idlist;
15 uid_t uid;
16
17 if (argc == 1)
18 {
19 mu_error ("usage: %s [+-]mode... file...", argv[0]);
20 exit (1);
21 }
22
23 rc = mu_list_create (&idlist);
24 if (rc)
25 {
26 mu_error ("mu_list_create: %s", mu_strerror (rc));
27 exit (1);
28 }
29 uid = getuid ();
30
31 for (i = 1; i < argc; i++)
32 {
33 if (argv[i][0] == '-' || argv[i][0] == '+')
34 {
35 rc = mu_file_safety_name_to_code (argv[i] + 1, &m);
36 if (rc)
37 {
38 mu_error ("%s: %s", argv[i], mu_strerror (rc));
39 exit (1);
40 }
41 if (argv[i][0] == '-')
42 mode &= ~m;
43 else
44 mode |= m;
45 }
46 else
47 {
48 rc = mu_file_safety_check (argv[i], mode, uid, idlist);
49 printf ("%s: %s\n", argv[i], mu_strerror (rc));
50 }
51 }
52 exit (0);
53}