]>
Commit | Line | Data |
---|---|---|
bb330e25 AF |
1 | commit 9a3c6a6ff602c88d7155139a7d7d0000b7b7e946 |
2 | Author: Siddhesh Poyarekar <siddhesh@redhat.com> | |
3 | Date: Thu Jan 2 10:05:27 2014 +0530 | |
4 | ||
5 | Fix return code from getent netgroup when the netgroup is not found (bz #16366) | |
6 | ||
7 | nscd incorrectly returns a success even when the netgroup in question | |
8 | is not found and adds a positive result in the cache. this patch | |
9 | fixes this behaviour by adding a negative lookup entry to cache and | |
10 | returning an error when the netgroup is not found. | |
11 | ||
12 | diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c | |
13 | index 50936ee..9fc1664 100644 | |
14 | --- a/nscd/netgroupcache.c | |
15 | +++ b/nscd/netgroupcache.c | |
16 | @@ -65,6 +65,55 @@ struct dataset | |
17 | char strdata[0]; | |
18 | }; | |
19 | ||
20 | +/* Sends a notfound message and prepares a notfound dataset to write to the | |
21 | + cache. Returns true if there was enough memory to allocate the dataset and | |
22 | + returns the dataset in DATASETP, total bytes to write in TOTALP and the | |
23 | + timeout in TIMEOUTP. KEY_COPY is set to point to the copy of the key in the | |
24 | + dataset. */ | |
25 | +static bool | |
26 | +do_notfound (struct database_dyn *db, int fd, request_header *req, | |
27 | + const char *key, struct dataset **datasetp, ssize_t *totalp, | |
28 | + time_t *timeoutp, char **key_copy) | |
29 | +{ | |
30 | + struct dataset *dataset; | |
31 | + ssize_t total; | |
32 | + time_t timeout; | |
33 | + bool cacheable = false; | |
34 | + | |
35 | + total = sizeof (notfound); | |
36 | + timeout = time (NULL) + db->negtimeout; | |
37 | + | |
38 | + if (fd != -1) | |
39 | + TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); | |
40 | + | |
41 | + dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); | |
42 | + /* If we cannot permanently store the result, so be it. */ | |
43 | + if (dataset != NULL) | |
44 | + { | |
45 | + dataset->head.allocsize = sizeof (struct dataset) + req->key_len; | |
46 | + dataset->head.recsize = total; | |
47 | + dataset->head.notfound = true; | |
48 | + dataset->head.nreloads = 0; | |
49 | + dataset->head.usable = true; | |
50 | + | |
51 | + /* Compute the timeout time. */ | |
52 | + timeout = dataset->head.timeout = time (NULL) + db->negtimeout; | |
53 | + dataset->head.ttl = db->negtimeout; | |
54 | + | |
55 | + /* This is the reply. */ | |
56 | + memcpy (&dataset->resp, ¬found, total); | |
57 | + | |
58 | + /* Copy the key data. */ | |
59 | + memcpy (dataset->strdata, key, req->key_len); | |
60 | + *key_copy = dataset->strdata; | |
61 | + | |
62 | + cacheable = true; | |
63 | + } | |
64 | + *timeoutp = timeout; | |
65 | + *totalp = total; | |
66 | + *datasetp = dataset; | |
67 | + return cacheable; | |
68 | +} | |
69 | ||
70 | static time_t | |
71 | addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, | |
72 | @@ -84,6 +133,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, | |
73 | struct dataset *dataset; | |
74 | bool cacheable = false; | |
75 | ssize_t total; | |
76 | + bool found = false; | |
77 | ||
78 | char *key_copy = NULL; | |
79 | struct __netgrent data; | |
80 | @@ -103,35 +153,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, | |
81 | && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database)) | |
82 | { | |
83 | /* No such service. */ | |
84 | - total = sizeof (notfound); | |
85 | - timeout = time (NULL) + db->negtimeout; | |
86 | - | |
87 | - if (fd != -1) | |
88 | - TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); | |
89 | - | |
90 | - dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); | |
91 | - /* If we cannot permanently store the result, so be it. */ | |
92 | - if (dataset != NULL) | |
93 | - { | |
94 | - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; | |
95 | - dataset->head.recsize = total; | |
96 | - dataset->head.notfound = true; | |
97 | - dataset->head.nreloads = 0; | |
98 | - dataset->head.usable = true; | |
99 | - | |
100 | - /* Compute the timeout time. */ | |
101 | - timeout = dataset->head.timeout = time (NULL) + db->negtimeout; | |
102 | - dataset->head.ttl = db->negtimeout; | |
103 | - | |
104 | - /* This is the reply. */ | |
105 | - memcpy (&dataset->resp, ¬found, total); | |
106 | - | |
107 | - /* Copy the key data. */ | |
108 | - memcpy (dataset->strdata, key, req->key_len); | |
109 | - | |
110 | - cacheable = true; | |
111 | - } | |
112 | - | |
113 | + cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, | |
114 | + &key_copy); | |
115 | goto writeout; | |
116 | } | |
117 | ||
118 | @@ -167,6 +190,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, | |
119 | ||
120 | if (status == NSS_STATUS_SUCCESS) | |
121 | { | |
122 | + found = true; | |
123 | union | |
124 | { | |
125 | enum nss_status (*f) (struct __netgrent *, char *, size_t, | |
126 | @@ -326,6 +350,15 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, | |
127 | } | |
128 | } | |
129 | ||
130 | + /* No results. Return a failure and write out a notfound record in the | |
131 | + cache. */ | |
132 | + if (!found) | |
133 | + { | |
134 | + cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, | |
135 | + &key_copy); | |
136 | + goto writeout; | |
137 | + } | |
138 | + | |
139 | total = buffilled; | |
140 | ||
141 | /* Fill in the dataset. */ |