1/* Copyright (C) 1997-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
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 <errno.h>
20#include <hesiod.h>
21#include <pwd.h>
22#include <nss.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27NSS_DECLARE_MODULE_FUNCTIONS (hesiod)
28
29/* Get the declaration of the parser function. */
30#define ENTNAME pwent
31#define STRUCTURE passwd
32#define EXTERN_PARSER
33#include <nss/nss_files/files-parse.c>
34
35enum nss_status
36_nss_hesiod_setpwent (int stayopen)
37{
38 return NSS_STATUS_SUCCESS;
39}
40
41enum nss_status
42_nss_hesiod_endpwent (void)
43{
44 return NSS_STATUS_SUCCESS;
45}
46
47static enum nss_status
48lookup (const char *name, const char *type, struct passwd *pwd,
49 char *buffer, size_t buflen, int *errnop)
50{
51 struct parser_data *data = (void *) buffer;
52 size_t linebuflen;
53 void *context;
54 char **list;
55 int parse_res;
56 size_t len;
57 int olderr = errno;
58
59 if (hesiod_init (&context) < 0)
60 return NSS_STATUS_UNAVAIL;
61
62 list = hesiod_resolve (context, name, type);
63 if (list == NULL)
64 {
65 int err = errno;
66 hesiod_end (context);
67 __set_errno (olderr);
68 return err == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
69 }
70
71 linebuflen = buffer + buflen - data->linebuffer;
72 len = strlen (*list) + 1;
73 if (linebuflen < len)
74 {
75 hesiod_free_list (context, list);
76 hesiod_end (context);
77 *errnop = ERANGE;
78 return NSS_STATUS_TRYAGAIN;
79 }
80
81 memcpy (data->linebuffer, *list, len);
82 hesiod_free_list (context, list);
83 hesiod_end (context);
84
85 parse_res = _nss_files_parse_pwent (buffer, pwd, data, buflen, errnop);
86 if (parse_res < 1)
87 {
88 __set_errno (olderr);
89 return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
90 }
91
92 return NSS_STATUS_SUCCESS;
93}
94
95enum nss_status
96_nss_hesiod_getpwnam_r (const char *name, struct passwd *pwd,
97 char *buffer, size_t buflen, int *errnop)
98{
99 return lookup (name, "passwd", pwd, buffer, buflen, errnop);
100}
101
102enum nss_status
103_nss_hesiod_getpwuid_r (uid_t uid, struct passwd *pwd,
104 char *buffer, size_t buflen, int *errnop)
105{
106 char uidstr[21]; /* We will probably never have a gid_t with more
107 than 64 bits. */
108
109 snprintf (uidstr, sizeof uidstr, "%d", uid);
110
111 return lookup (uidstr, "uid", pwd, buffer, buflen, errnop);
112}
113