CVE-2014-8121: Do not close NSS files database during iteration [BZ #18007]
[platform/upstream/glibc.git] / nss / tst-nss-getpwent.c
1 /* Copyright (C) 2015 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <http://www.gnu.org/licenses/>.  */
17
18 #include <pwd.h>
19 #include <stdbool.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 int
25 do_test (void)
26 {
27   /* Count the number of entries in the password database, and fetch
28      data from the first and last entries.  */
29   size_t count = 0;
30   struct passwd * pw;
31   char *first_name = NULL;
32   uid_t first_uid = 0;
33   char *last_name = NULL;
34   uid_t last_uid = 0;
35   setpwent ();
36   while ((pw  = getpwent ()) != NULL)
37     {
38       if (first_name == NULL)
39         {
40           first_name = strdup (pw->pw_name);
41           if (first_name == NULL)
42             {
43               printf ("strdup: %m\n");
44               return 1;
45             }
46           first_uid = pw->pw_uid;
47         }
48
49       free (last_name);
50       last_name = strdup (pw->pw_name);
51       if (last_name == NULL)
52         {
53           printf ("strdup: %m\n");
54           return 1;
55         }
56       last_uid = pw->pw_uid;
57       ++count;
58     }
59   endpwent ();
60
61   if (count == 0)
62     {
63       printf ("No entries in the password database.\n");
64       return 0;
65     }
66
67   /* Try again, this time interleaving with name-based and UID-based
68      lookup operations.  The counts do not match if the interleaved
69      lookups affected the enumeration.  */
70   size_t new_count = 0;
71   setpwent ();
72   while ((pw  = getpwent ()) != NULL)
73     {
74       if (new_count == count)
75         {
76           printf ("Additional entry in the password database.\n");
77           return 1;
78         }
79       ++new_count;
80       struct passwd *pw2 = getpwnam (first_name);
81       if (pw2 == NULL)
82         {
83           printf ("getpwnam (%s) failed: %m\n", first_name);
84           return 1;
85         }
86       pw2 = getpwnam (last_name);
87       if (pw2 == NULL)
88         {
89           printf ("getpwnam (%s) failed: %m\n", last_name);
90           return 1;
91         }
92       pw2 = getpwuid (first_uid);
93       if (pw2 == NULL)
94         {
95           printf ("getpwuid (%llu) failed: %m\n",
96                   (unsigned long long) first_uid);
97           return 1;
98         }
99       pw2 = getpwuid (last_uid);
100       if (pw2 == NULL)
101         {
102           printf ("getpwuid (%llu) failed: %m\n",
103                   (unsigned long long) last_uid);
104           return 1;
105         }
106     }
107   endpwent ();
108   if (new_count < count)
109     {
110       printf ("Missing entry in the password database.\n");
111       return 1;
112     }
113
114   return 0;
115 }
116
117 #define TEST_FUNCTION do_test ()
118 #include "../test-skeleton.c"