Commit | Line | Data |
---|---|---|
0756eb3c PH |
1 | /************************************************* |
2 | * Exim - an Internet mail transport agent * | |
3 | *************************************************/ | |
4 | ||
3386088d | 5 | /* Copyright (c) University of Cambridge 1995 - 2015 */ |
0756eb3c PH |
6 | /* See the file NOTICE for conditions of use and distribution. */ |
7 | ||
8 | /* The idea for this code came from Matthew Byng-Maddick, but his original has | |
0f2cbd1b MH |
9 | been heavily reworked a lot for Exim 4 (and it now uses stat() (more precisely: |
10 | lstat()) rather than a directory scan). */ | |
0756eb3c PH |
11 | |
12 | ||
13 | #include "../exim.h" | |
14 | #include "lf_functions.h" | |
0756eb3c PH |
15 | |
16 | ||
17 | ||
18 | /************************************************* | |
19 | * Open entry point * | |
20 | *************************************************/ | |
21 | ||
22 | /* See local README for interface description. We open the directory to test | |
23 | whether it exists and whether it is searchable. However, we don't need to keep | |
0f2cbd1b | 24 | it open, because the "search" can be done by a call to lstat() rather than |
0756eb3c PH |
25 | actually scanning through the list of files. */ |
26 | ||
e6d225ae | 27 | static void * |
d447dbd1 | 28 | dsearch_open(const uschar * dirname, uschar ** errmsg) |
0756eb3c | 29 | { |
54a2a2a9 | 30 | DIR * dp = exim_opendir(dirname); |
36b600bb | 31 | if (!dp) |
0756eb3c PH |
32 | { |
33 | int save_errno = errno; | |
34 | *errmsg = string_open_failed(errno, "%s for directory search", dirname); | |
35 | errno = save_errno; | |
36 | return NULL; | |
37 | } | |
38 | closedir(dp); | |
39 | return (void *)(-1); | |
40 | } | |
41 | ||
42 | ||
43 | /************************************************* | |
44 | * Check entry point * | |
45 | *************************************************/ | |
46 | ||
47 | /* The handle will always be (void *)(-1), but don't try casting it to an | |
48 | integer as this gives warnings on 64-bit systems. */ | |
49 | ||
36b600bb | 50 | static BOOL |
d447dbd1 JH |
51 | dsearch_check(void * handle, const uschar * filename, int modemask, |
52 | uid_t * owners, gid_t * owngroups, uschar ** errmsg) | |
0756eb3c PH |
53 | { |
54 | handle = handle; | |
129a5d13 JH |
55 | if (*filename == '/') |
56 | return lf_check_file(-1, filename, S_IFDIR, modemask, owners, owngroups, | |
57 | "dsearch", errmsg) == 0; | |
58 | *errmsg = string_sprintf("dirname '%s' for dsearch is not absolute", filename); | |
59 | return FALSE; | |
0756eb3c PH |
60 | } |
61 | ||
62 | ||
63 | /************************************************* | |
64 | * Find entry point * | |
65 | *************************************************/ | |
66 | ||
0f2cbd1b | 67 | /* See local README for interface description. We use lstat() instead of |
0756eb3c PH |
68 | scanning the directory, as it is hopefully faster to let the OS do the scanning |
69 | for us. */ | |
70 | ||
13e70f55 | 71 | static int |
d447dbd1 | 72 | dsearch_find(void * handle, const uschar * dirname, const uschar * keystring, |
67a57a5a JH |
73 | int length, uschar ** result, uschar ** errmsg, uint * do_cache, |
74 | const uschar * opts) | |
0756eb3c PH |
75 | { |
76 | struct stat statbuf; | |
77 | int save_errno; | |
13e70f55 | 78 | uschar * filename; |
0756eb3c PH |
79 | |
80 | handle = handle; /* Keep picky compilers happy */ | |
81 | length = length; | |
82 | do_cache = do_cache; | |
83 | ||
84 | if (Ustrchr(keystring, '/') != 0) | |
85 | { | |
86 | *errmsg = string_sprintf("key for dsearch lookup contains a slash: %s", | |
87 | keystring); | |
88 | return DEFER; | |
89 | } | |
90 | ||
13e70f55 | 91 | filename = string_sprintf("%s/%s", dirname, keystring); |
0f2cbd1b | 92 | if (Ulstat(filename, &statbuf) >= 0) |
0756eb3c | 93 | { |
36b600bb JH |
94 | /* Since the filename exists in the filesystem, we can return a |
95 | non-tainted result. */ | |
96 | *result = string_copy_taint(keystring, FALSE); | |
0756eb3c PH |
97 | return OK; |
98 | } | |
99 | ||
100 | if (errno == ENOENT) return FAIL; | |
101 | ||
102 | save_errno = errno; | |
0f2cbd1b | 103 | *errmsg = string_sprintf("%s: lstat failed", filename); |
0756eb3c PH |
104 | errno = save_errno; |
105 | return DEFER; | |
106 | } | |
107 | ||
108 | ||
109 | /************************************************* | |
110 | * Close entry point * | |
111 | *************************************************/ | |
112 | ||
113 | /* See local README for interface description */ | |
114 | ||
115 | void | |
e6d225ae | 116 | static dsearch_close(void *handle) |
0756eb3c PH |
117 | { |
118 | handle = handle; /* Avoid compiler warning */ | |
119 | } | |
120 | ||
6545de78 PP |
121 | |
122 | /************************************************* | |
123 | * Version reporting entry point * | |
124 | *************************************************/ | |
125 | ||
126 | /* See local README for interface description. */ | |
127 | ||
128 | #include "../version.h" | |
129 | ||
130 | void | |
131 | dsearch_version_report(FILE *f) | |
132 | { | |
133 | #ifdef DYNLOOKUP | |
134 | fprintf(f, "Library version: dsearch: Exim version %s\n", EXIM_VERSION_STR); | |
135 | #endif | |
136 | } | |
137 | ||
138 | ||
e6d225ae DW |
139 | static lookup_info _lookup_info = { |
140 | US"dsearch", /* lookup name */ | |
141 | lookup_absfile, /* uses absolute file name */ | |
142 | dsearch_open, /* open function */ | |
143 | dsearch_check, /* check function */ | |
144 | dsearch_find, /* find function */ | |
145 | dsearch_close, /* close function */ | |
146 | NULL, /* no tidy function */ | |
6545de78 PP |
147 | NULL, /* no quoting function */ |
148 | dsearch_version_report /* version reporting */ | |
e6d225ae DW |
149 | }; |
150 | ||
151 | #ifdef DYNLOOKUP | |
152 | #define dsearch_lookup_module_info _lookup_module_info | |
153 | #endif | |
154 | ||
155 | static lookup_info *_lookup_list[] = { &_lookup_info }; | |
156 | lookup_module_info dsearch_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 1 }; | |
157 | ||
0756eb3c | 158 | /* End of lookups/dsearch.c */ |