]> git.ipfire.org Git - thirdparty/glibc.git/blob - nss/nsswitch.c
nsswitch: handle missing actions properly
[thirdparty/glibc.git] / nss / nsswitch.c
1 /* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <ctype.h>
20 #include <dlfcn.h>
21 #include <errno.h>
22 #include <netdb.h>
23 #include <libc-lock.h>
24 #include <search.h>
25 #include <stdio.h>
26 #include <stdio_ext.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <aliases.h>
31 #include <grp.h>
32 #include <netinet/ether.h>
33 #include <pwd.h>
34 #include <shadow.h>
35 #include <unistd.h>
36
37 #if !defined DO_STATIC_NSS || defined SHARED
38 # include <gnu/lib-names.h>
39 #endif
40
41 #include "nsswitch.h"
42 #include "../nscd/nscd_proto.h"
43 #include <sysdep.h>
44 #include <config.h>
45
46 /* Declare external database variables. */
47 #define DEFINE_DATABASE(name) \
48 nss_action_list __nss_##name##_database attribute_hidden; \
49 weak_extern (__nss_##name##_database)
50 #include "databases.def"
51 #undef DEFINE_DATABASE
52
53
54 #undef DEFINE_DATABASE
55 #define DEFINE_DATABASE(name) #name,
56 static const char * database_names[] = {
57 #include "databases.def"
58 NULL
59 };
60
61 #ifdef USE_NSCD
62 /* Flags whether custom rules for database is set. */
63 bool __nss_database_custom[NSS_DBSIDX_max];
64 #endif
65
66
67 /*__libc_lock_define_initialized (static, lock)*/
68
69 /* -1 == database not found
70 0 == database entry pointer stored */
71 int
72 __nss_database_lookup2 (const char *database, const char *alternate_name,
73 const char *defconfig, nss_action_list *ni)
74 {
75 int database_id;
76
77 for (database_id = 0; database_names[database_id]; database_id++)
78 if (strcmp (database_names[database_id], database) == 0)
79 break;
80
81 if (database_names[database_id] == NULL)
82 return -1;
83
84 /* If *NI is NULL, the database was not mentioned in nsswitch.conf.
85 If *NI is not NULL, but *NI->module is NULL, the database was in
86 nsswitch.conf but listed no actions. We test for the former. */
87 if (__nss_database_get (database_id, ni) && *ni != NULL)
88 {
89 /* Success. */
90 return 0;
91 }
92 else
93 {
94 /* Failure. */
95 return -1;
96 }
97 }
98 libc_hidden_def (__nss_database_lookup2)
99
100
101 /* -1 == not found
102 0 == function found
103 1 == finished */
104 int
105 __nss_lookup (nss_action_list *ni, const char *fct_name, const char *fct2_name,
106 void **fctp)
107 {
108 *fctp = __nss_lookup_function (*ni, fct_name);
109 if (*fctp == NULL && fct2_name != NULL)
110 *fctp = __nss_lookup_function (*ni, fct2_name);
111
112 while (*fctp == NULL
113 && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
114 && (*ni)[1].module != NULL)
115 {
116 ++(*ni);
117
118 *fctp = __nss_lookup_function (*ni, fct_name);
119 if (*fctp == NULL && fct2_name != NULL)
120 *fctp = __nss_lookup_function (*ni, fct2_name);
121 }
122
123 return *fctp != NULL ? 0 : (*ni)[1].module == NULL ? 1 : -1;
124 }
125 libc_hidden_def (__nss_lookup)
126
127
128 /* -1 == not found
129 0 == adjusted for next function
130 1 == finished */
131 int
132 __nss_next2 (nss_action_list *ni, const char *fct_name, const char *fct2_name,
133 void **fctp, int status, int all_values)
134 {
135 if (all_values)
136 {
137 if (nss_next_action (*ni, NSS_STATUS_TRYAGAIN) == NSS_ACTION_RETURN
138 && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_RETURN
139 && nss_next_action (*ni, NSS_STATUS_NOTFOUND) == NSS_ACTION_RETURN
140 && nss_next_action (*ni, NSS_STATUS_SUCCESS) == NSS_ACTION_RETURN)
141 return 1;
142 }
143 else
144 {
145 /* This is really only for debugging. */
146 if (__builtin_expect (NSS_STATUS_TRYAGAIN > status
147 || status > NSS_STATUS_RETURN, 0))
148 __libc_fatal ("Illegal status in __nss_next.\n");
149
150 if (nss_next_action (*ni, status) == NSS_ACTION_RETURN)
151 return 1;
152 }
153
154 if ((*ni)[1].module == NULL)
155 return -1;
156
157 do
158 {
159 ++(*ni);
160
161 *fctp = __nss_lookup_function (*ni, fct_name);
162 if (*fctp == NULL && fct2_name != NULL)
163 *fctp = __nss_lookup_function (*ni, fct2_name);
164 }
165 while (*fctp == NULL
166 && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
167 && (*ni)[1].module != NULL);
168
169 return *fctp != NULL ? 0 : -1;
170 }
171 libc_hidden_def (__nss_next2)
172
173 void *
174 __nss_lookup_function (nss_action_list ni, const char *fct_name)
175 {
176 if (ni->module == NULL)
177 return NULL;
178 return __nss_module_get_function (ni->module, fct_name);
179 }
180 libc_hidden_def (__nss_lookup_function)