1 /* Copyright (c) 1997-2022 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    <https://www.gnu.org/licenses/>.  */
17 
18 #include <assert.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdint.h>
23 #include <sys/types.h>
24 #include <rpc/rpc.h>
25 #include <rpcsvc/nis.h>
26 #include <shlib-compat.h>
27 
28 #define DEFAULT_TTL 43200
29 
30 /*
31 ** Some functions for parsing the -D param and NIS_DEFAULTS Environ
32 */
33 static nis_name
searchXYX(char * str,const char * what)34 searchXYX (char *str, const char *what)
35 {
36   assert (strlen (what) == 6);
37   assert (strncmp (str, what, 6) == 0);
38   str += 6;			/* Points to the begin of the parameters.  */
39 
40   int i = 0;
41   while (str[i] != '\0' && str[i] != ':')
42     ++i;
43   if (i == 0)			/* only "<WHAT>=" ? */
44     return strdup ("");
45 
46   return strndup (str, i);
47 }
48 
49 
50 static nis_name
searchgroup(char * str)51 searchgroup (char *str)
52 {
53   return searchXYX (str, "group=");
54 }
55 
56 
57 static nis_name
searchowner(char * str)58 searchowner (char *str)
59 {
60   return searchXYX (str, "owner=");
61 }
62 
63 
64 static uint32_t
searchttl(char * str)65 searchttl (char *str)
66 {
67   char buf[strlen (str) + 1];
68   char *cptr, *dptr;
69   uint32_t time;
70   int i;
71 
72   dptr = strstr (str, "ttl=");
73   if (dptr == NULL)		/* should (could) not happen */
74     return DEFAULT_TTL;;
75 
76   dptr += 4;			/* points to the begin of the new ttl */
77   i = 0;
78   while (dptr[i] != '\0' && dptr[i] != ':')
79     i++;
80   if (i == 0)			/* only "ttl=" ? */
81     return DEFAULT_TTL;
82 
83   strncpy (buf, dptr, i);
84   buf[i] = '\0';
85   time = 0;
86 
87   dptr = buf;
88   cptr = strchr (dptr, 'd');
89   if (cptr != NULL)
90     {
91       *cptr = '\0';
92       cptr++;
93       time += atoi (dptr) * 60 * 60 * 24;
94       dptr = cptr;
95     }
96 
97   cptr = strchr (dptr, 'h');
98   if (cptr != NULL)
99     {
100       *cptr = '\0';
101       cptr++;
102       time += atoi (dptr) * 60 * 60;
103       dptr = cptr;
104     }
105 
106   cptr = strchr (dptr, 'm');
107   if (cptr != NULL)
108     {
109       *cptr = '\0';
110       cptr++;
111       time += atoi (dptr) * 60;
112       dptr = cptr;
113     }
114 
115   cptr = strchr (dptr, 's');
116   if (cptr != NULL)
117     *cptr = '\0';
118 
119   time += atoi (dptr);
120 
121   return time;
122 }
123 
124 static unsigned int
searchaccess(char * str,unsigned int access)125 searchaccess (char *str, unsigned int access)
126 {
127   char buf[strlen (str) + 1];
128   char *cptr;
129   unsigned int result = access;
130   int i;
131   int n, o, g, w;
132 
133   cptr = strstr (str, "access=");
134   if (cptr == NULL)
135     return 0;
136 
137   cptr += 7;			/* points to the begin of the access string */
138   i = 0;
139   while (cptr[i] != '\0' && cptr[i] != ':')
140     i++;
141   if (i == 0)			/* only "access=" ? */
142     return 0;
143 
144   strncpy (buf, cptr, i);
145   buf[i] = '\0';
146 
147   n = o = g = w = 0;
148   cptr = buf;
149   if (*cptr == ',') /* Fix for stupid Solaris scripts */
150     ++cptr;
151   while (*cptr != '\0')
152     {
153       switch (*cptr)
154 	{
155 	case 'n':
156 	  n = 1;
157 	  break;
158 	case 'o':
159 	  o = 1;
160 	  break;
161 	case 'g':
162 	  g = 1;
163 	  break;
164 	case 'w':
165 	  w = 1;
166 	  break;
167 	case 'a':
168 	  o = g = w = 1;
169 	  break;
170 	case '-':
171 	  cptr++;		/* Remove "-" from beginning */
172 	  while (*cptr != '\0' && *cptr != ',')
173 	    {
174 	      switch (*cptr)
175 		{
176 		case 'r':
177 		  if (n)
178 		    result = result & ~(NIS_READ_ACC << 24);
179 		  if (o)
180 		    result = result & ~(NIS_READ_ACC << 16);
181 		  if (g)
182 		    result = result & ~(NIS_READ_ACC << 8);
183 		  if (w)
184 		    result = result & ~(NIS_READ_ACC);
185 		  break;
186 		case 'm':
187 		  if (n)
188 		    result = result & ~(NIS_MODIFY_ACC << 24);
189 		  if (o)
190 		    result = result & ~(NIS_MODIFY_ACC << 16);
191 		  if (g)
192 		    result = result & ~(NIS_MODIFY_ACC << 8);
193 		  if (w)
194 		    result = result & ~(NIS_MODIFY_ACC);
195 		  break;
196 		case 'c':
197 		  if (n)
198 		    result = result & ~(NIS_CREATE_ACC << 24);
199 		  if (o)
200 		    result = result & ~(NIS_CREATE_ACC << 16);
201 		  if (g)
202 		    result = result & ~(NIS_CREATE_ACC << 8);
203 		  if (w)
204 		    result = result & ~(NIS_CREATE_ACC);
205 		  break;
206 		case 'd':
207 		  if (n)
208 		    result = result & ~(NIS_DESTROY_ACC << 24);
209 		  if (o)
210 		    result = result & ~(NIS_DESTROY_ACC << 16);
211 		  if (g)
212 		    result = result & ~(NIS_DESTROY_ACC << 8);
213 		  if (w)
214 		    result = result & ~(NIS_DESTROY_ACC);
215 		  break;
216 		default:
217 		  return (~0U);
218 		}
219 	      cptr++;
220 	    }
221 	  n = o = g = w = 0;
222 	  break;
223 	case '+':
224 	  cptr++;		/* Remove "+" from beginning */
225 	  while (*cptr != '\0' && *cptr != ',')
226 	    {
227 	      switch (*cptr)
228 		{
229 		case 'r':
230 		  if (n)
231 		    result = result | (NIS_READ_ACC << 24);
232 		  if (o)
233 		    result = result | (NIS_READ_ACC << 16);
234 		  if (g)
235 		    result = result | (NIS_READ_ACC << 8);
236 		  if (w)
237 		    result = result | (NIS_READ_ACC);
238 		  break;
239 		case 'm':
240 		  if (n)
241 		    result = result | (NIS_MODIFY_ACC << 24);
242 		  if (o)
243 		    result = result | (NIS_MODIFY_ACC << 16);
244 		  if (g)
245 		    result = result | (NIS_MODIFY_ACC << 8);
246 		  if (w)
247 		    result = result | (NIS_MODIFY_ACC);
248 		  break;
249 		case 'c':
250 		  if (n)
251 		    result = result | (NIS_CREATE_ACC << 24);
252 		  if (o)
253 		    result = result | (NIS_CREATE_ACC << 16);
254 		  if (g)
255 		    result = result | (NIS_CREATE_ACC << 8);
256 		  if (w)
257 		    result = result | (NIS_CREATE_ACC);
258 		  break;
259 		case 'd':
260 		  if (n)
261 		    result = result | (NIS_DESTROY_ACC << 24);
262 		  if (o)
263 		    result = result | (NIS_DESTROY_ACC << 16);
264 		  if (g)
265 		    result = result | (NIS_DESTROY_ACC << 8);
266 		  if (w)
267 		    result = result | (NIS_DESTROY_ACC);
268 		  break;
269 		default:
270 		  return (~0U);
271 		}
272 	      cptr++;
273 	    }
274 	  n = o = g = w = 0;
275 	  break;
276 	case '=':
277 	  cptr++;		/* Remove "=" from beginning */
278 	  /* Clear */
279 	  if (n)
280 	    result = result & ~((NIS_READ_ACC + NIS_MODIFY_ACC
281 				 + NIS_CREATE_ACC + NIS_DESTROY_ACC) << 24);
282 
283 	  if (o)
284 	    result = result & ~((NIS_READ_ACC + NIS_MODIFY_ACC
285 				 + NIS_CREATE_ACC + NIS_DESTROY_ACC) << 16);
286 	  if (g)
287 	    result = result & ~((NIS_READ_ACC + NIS_MODIFY_ACC
288 				 + NIS_CREATE_ACC + NIS_DESTROY_ACC) << 8);
289 	  if (w)
290 	    result = result & ~(NIS_READ_ACC + NIS_MODIFY_ACC
291 				+ NIS_CREATE_ACC + NIS_DESTROY_ACC);
292 	  while (*cptr != '\0' && *cptr != ',')
293 	    {
294 	      switch (*cptr)
295 		{
296 		case 'r':
297 		  if (n)
298 		    result = result | (NIS_READ_ACC << 24);
299 		  if (o)
300 		    result = result | (NIS_READ_ACC << 16);
301 		  if (g)
302 		    result = result | (NIS_READ_ACC << 8);
303 		  if (w)
304 		    result = result | (NIS_READ_ACC);
305 		  break;
306 		case 'm':
307 		  if (n)
308 		    result = result | (NIS_MODIFY_ACC << 24);
309 		  if (o)
310 		    result = result | (NIS_MODIFY_ACC << 16);
311 		  if (g)
312 		    result = result | (NIS_MODIFY_ACC << 8);
313 		  if (w)
314 		    result = result | (NIS_MODIFY_ACC);
315 		  break;
316 		case 'c':
317 		  if (n)
318 		    result = result | (NIS_CREATE_ACC << 24);
319 		  if (o)
320 		    result = result | (NIS_CREATE_ACC << 16);
321 		  if (g)
322 		    result = result | (NIS_CREATE_ACC << 8);
323 		  if (w)
324 		    result = result | (NIS_CREATE_ACC);
325 		  break;
326 		case 'd':
327 		  if (n)
328 		    result = result | (NIS_DESTROY_ACC << 24);
329 		  if (o)
330 		    result = result | (NIS_DESTROY_ACC << 16);
331 		  if (g)
332 		    result = result | (NIS_DESTROY_ACC << 8);
333 		  if (w)
334 		    result = result | (NIS_DESTROY_ACC);
335 		  break;
336 		default:
337 		  return result = (~0U);
338 		}
339 	      cptr++;
340 	    }
341 	  n = o = g = w = 0;
342 	  break;
343 	default:
344 	  return result = (~0U);
345 	}
346       if (*cptr != '\0')
347 	cptr++;
348     }
349 
350   return result;
351 }
352 
353 
354 nis_name
__nis_default_owner(char * defaults)355 __nis_default_owner (char *defaults)
356 {
357   char *default_owner = NULL;
358 
359   char *cptr = defaults;
360   if (cptr == NULL)
361     cptr = getenv ("NIS_DEFAULTS");
362 
363   if (cptr != NULL)
364     {
365       char *dptr = strstr (cptr, "owner=");
366       if (dptr != NULL)
367 	{
368 	  char *p = searchowner (dptr);
369 	  if (p == NULL)
370 	    return NULL;
371 	  default_owner = strdupa (p);
372 	  free (p);
373 	}
374     }
375 
376   return strdup (default_owner ?: nis_local_principal ());
377 }
libnsl_hidden_nolink_def(__nis_default_owner,GLIBC_2_1)378 libnsl_hidden_nolink_def (__nis_default_owner, GLIBC_2_1)
379 
380 
381 nis_name
382 __nis_default_group (char *defaults)
383 {
384   char *default_group = NULL;
385 
386   char *cptr = defaults;
387   if (cptr == NULL)
388     cptr = getenv ("NIS_DEFAULTS");
389 
390   if (cptr != NULL)
391     {
392       char *dptr = strstr (cptr, "group=");
393       if (dptr != NULL)
394 	{
395 	  char *p = searchgroup (dptr);
396 	  if (p == NULL)
397 	    return NULL;
398 	  default_group = strdupa (p);
399 	  free (p);
400 	}
401     }
402 
403   return strdup (default_group ?: nis_local_group ());
404 }
libnsl_hidden_nolink_def(__nis_default_group,GLIBC_2_1)405 libnsl_hidden_nolink_def (__nis_default_group, GLIBC_2_1)
406 
407 
408 uint32_t
409 __nis_default_ttl (char *defaults)
410 {
411   char *cptr, *dptr;
412 
413   if (defaults != NULL)
414     {
415       dptr = strstr (defaults, "ttl=");
416       if (dptr != NULL)
417 	return searchttl (defaults);
418     }
419 
420   cptr = getenv ("NIS_DEFAULTS");
421   if (cptr == NULL)
422     return DEFAULT_TTL;
423 
424   dptr = strstr (cptr, "ttl=");
425   if (dptr == NULL)
426     return DEFAULT_TTL;
427 
428   return searchttl (cptr);
429 }
libnsl_hidden_nolink_def(__nis_default_ttl,GLIBC_2_1)430 libnsl_hidden_nolink_def (__nis_default_ttl, GLIBC_2_1)
431 
432 /* Default access rights are ----rmcdr---r---, but we could change
433    this with the NIS_DEFAULTS variable. */
434 unsigned int
435 __nis_default_access (char *param, unsigned int defaults)
436 {
437   unsigned int result;
438   char *cptr;
439 
440   if (defaults == 0)
441     result = 0 | OWNER_DEFAULT | GROUP_DEFAULT | WORLD_DEFAULT;
442   else
443     result = defaults;
444 
445   if (param != NULL && strstr (param, "access=") != NULL)
446     result = searchaccess (param, result);
447   else
448     {
449       cptr = getenv ("NIS_DEFAULTS");
450       if (cptr != NULL && strstr (cptr, "access=") != NULL)
451 	result = searchaccess (cptr, result);
452     }
453 
454   return result;
455 }
456 libnsl_hidden_nolink_def (__nis_default_access, GLIBC_2_1)
457