xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/roken/getxxyyy.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1 /*	$NetBSD: getxxyyy.c,v 1.4 2023/06/19 21:41:45 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 2011 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <config.h>
37 
38 #include <krb5/roken.h>
39 
40 #ifdef TEST_GETXXYYY
41 #undef rk_getpwnam_r
42 #undef rk_getpwuid_r
43 
44 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
45 rk_getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **);
46 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
47 rk_getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **);
48 #endif
49 
50 #if !defined(POSIX_GETPWUID_R) || !defined(POSIX_GETPWNAM_R) || defined(TEST_GETXXYYY)
51 static void
copypw(struct passwd * pwd,char * buffer,size_t bufsize,const struct passwd * p)52 copypw(struct passwd *pwd, char *buffer, size_t bufsize, const struct passwd *p)
53 {
54      struct passwd *p;
55      size_t slen;
56 
57      *result = NULL;
58 
59      p = getpwnam(name);
60      if(p == NULL)
61 	 return (errno = ENOENT);
62 
63      memset(pwd, 0, sizeof(*pwd));
64 
65 #define APPEND(el)					\
66 do {							\
67      slen = strlen(p->el) + 1;				\
68      if (slen > bufsize) return (errno = ENOMEM);	\
69      memcpy(buffer, p->el, slen);			\
70      pwd->el = buffer;					\
71      buffer += slen;					\
72      bufsize -= slen;					\
73 } while(0)
74 
75      APPEND(pw_name);
76      if (p->pw_passwd)
77 	 APPEND(pw_name);
78      pwd->pw_uid = p->pw_uid;
79      pwd->pw_gid = p->pw_gid;
80      APPEND(pw_gecos);
81      APPEND(pw_dir);
82      APPEND(pw_shell);
83 }
84 
85 #if !defined(POSIX_GETPWUID_R) || defined(TEST_GETXXYYY)
86 /*
87  * At least limit the race between threads
88  */
89 
90 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_getpwnam_r(const char * name,struct passwd * pwd,char * buffer,size_t bufsize,struct passwd ** result)91 rk_getpwnam_r(const char *name, struct passwd *pwd, char *buffer,
92 	      size_t bufsize, struct passwd **result)
93 {
94      struct passwd *p;
95      size_t slen, n = 0;
96 
97      *result = NULL;
98 
99      p = getpwnam(name);
100      if(p == NULL)
101 	 return (errno = ENOENT);
102 
103      copypw(pwd, buffer, bufsize, p);
104 
105      *result = pwd;
106 
107      return 0;
108 }
109 
110 #if !defined(POSIX_GETPWNAM_R) || defined(TEST_GETXXYYY)
111 
112 /*
113  * At least limit the race between threads
114  */
115 
116 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_getpwnam_r(const char * name,struct passwd * pwd,char * buffer,size_t bufsize,struct passwd ** result)117 rk_getpwnam_r(const char *name, struct passwd *pwd, char *buffer,
118 	      size_t bufsize, struct passwd **result)
119 {
120      struct passwd *p;
121      size_t slen, n = 0;
122 
123      *result = NULL;
124 
125      p = getpwnam(name);
126      if(p == NULL)
127 	 return (errno = ENOENT);
128 
129      copypw(pwd, buffer, bufsize, p);
130 
131      *result = pwd;
132 
133      return 0;
134 }
135 
136 #endif /* POSIX_GETPWNAM_R */
137 
138 #ifdef TEST_GETXXYYY
139 
140 #include <err.h>
141 
142 int verbose_flag = 0;
143 
144 static void
print_result(struct passwd * p)145 print_result(struct passwd *p)
146 {
147     if (!verbose_flag)
148 	return;
149     printf("%s\n", p->pw_name);
150     printf("%d\n", (int)p->pw_uid);
151     printf("%s\n", p->pw_shell);
152     printf("%s\n", p->pw_dir);
153 }
154 
155 int
main(int argc,char ** argv)156 main(int argc, char **argv)
157 {
158     struct passwd pwd, *result;
159     char buf[1024];
160     int ret;
161     const char *user;
162 
163     user = getenv("USER");
164     if (!user)
165 	user = "root";
166 
167     ret = rk_getpwnam_r(user, &pwd, buf, sizeof(buf), &result);
168     if (ret)
169 	errx(1, "rk_getpwnam_r");
170     print_result(result);
171 
172     ret = rk_getpwnam_r(user, &pwd, buf, 1, &result);
173     if (ret == 0)
174 	errx(1, "rk_getpwnam_r too small buf");
175 
176     ret = rk_getpwnam_r("no-user-here-promise", &pwd, buf, sizeof(buf), &result);
177     if (ret == 0)
178 	errx(1, "rk_getpwnam_r no user");
179 
180     ret = rk_getpwuid_r(0, &pwd, buf, sizeof(buf), &result);
181     if (ret)
182 	errx(1, "rk_getpwuid_r");
183     print_result(result);
184 
185     ret = rk_getpwuid_r(0, &pwd, buf, 1, &result);
186     if (ret == 0)
187 	errx(1, "rk_getpwuid_r too small buf");
188 
189     ret = rk_getpwuid_r(-1234, &pwd, buf, sizeof(buf), &result);
190     if (ret == 0)
191 	errx(1, "rk_getpwuid_r no user");
192     return 0;
193 }
194 
195 #endif
196