xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/roken/getxxyyy.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /*	$NetBSD: getxxyyy.c,v 1.3 2017/09/08 15:29:43 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
52 copypw(struct passwd *pwd, char *buffer, size_t bufsize, const struct passwd *p)
53 {
54      memset(pwd, 0, sizeof(*pwd));
55 
56 #define APPEND(el)					\
57 do {							\
58      slen = strlen(p->el) + 1;				\
59      if (slen > bufsize) return (errno = ENOMEM);	\
60      memcpy(buffer, p->el, slen);			\
61      pwd->el = buffer;					\
62      buffer += slen;					\
63      bufsize -= slen;					\
64 } while(0)
65 
66      APPEND(pw_name);
67      if (p->pw_passwd)
68 	 APPEND(pw_name);
69      pwd->pw_uid = p->pw_uid;
70      pwd->pw_gid = p->pw_gid;
71      APPEND(pw_gecos);
72      APPEND(pw_dir);
73      APPEND(pw_shell);
74 }
75 
76 #if !defined(POSIX_GETPWUID_R) || defined(TEST_GETXXYYY)
77 /*
78  * At least limit the race between threads
79  */
80 
81 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
82 rk_getpwnam_r(const char *name, struct passwd *pwd, char *buffer,
83 	      size_t bufsize, struct passwd **result)
84 {
85      struct passwd *p;
86      size_t slen, n = 0;
87 
88      *result = NULL;
89 
90      p = getpwnam(name);
91      if(p == NULL)
92 	 return (errno = ENOENT);
93 
94      copypw(pwd, buffer, bufsize, p);
95 
96      *result = pwd;
97 
98      return 0;
99 }
100 
101 #if !defined(POSIX_GETPWNAM_R) || defined(TEST_GETXXYYY)
102 
103 /*
104  * At least limit the race between threads
105  */
106 
107 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
108 rk_getpwnam_r(const char *name, struct passwd *pwd, char *buffer,
109 	      size_t bufsize, struct passwd **result)
110 {
111      struct passwd *p;
112      size_t slen, n = 0;
113 
114      *result = NULL;
115 
116      p = getpwnam(name);
117      if(p == NULL)
118 	 return (errno = ENOENT);
119 
120      copypw(pwd, buffer, bufsize, p);
121 
122      *result = pwd;
123 
124      return 0;
125 }
126 
127 #endif /* POSIX_GETPWNAM_R */
128 
129 #ifdef TEST_GETXXYYY
130 
131 #include <err.h>
132 
133 int verbose_flag = 0;
134 
135 static void
136 print_result(struct passwd *p)
137 {
138     if (!verbose_flag)
139 	return;
140     printf("%s\n", p->pw_name);
141     printf("%d\n", (int)p->pw_uid);
142     printf("%s\n", p->pw_shell);
143     printf("%s\n", p->pw_dir);
144 }
145 
146 int
147 main(int argc, char **argv)
148 {
149     struct passwd pwd, *result;
150     char buf[1024];
151     int ret;
152     const char *user;
153 
154     user = getenv("USER");
155     if (!user)
156 	user = "root";
157 
158     ret = rk_getpwnam_r(user, &pwd, buf, sizeof(buf), &result);
159     if (ret)
160 	errx(1, "rk_getpwnam_r");
161     print_result(result);
162 
163     ret = rk_getpwnam_r(user, &pwd, buf, 1, &result);
164     if (ret == 0)
165 	errx(1, "rk_getpwnam_r too small buf");
166 
167     ret = rk_getpwnam_r("no-user-here-promise", &pwd, buf, sizeof(buf), &result);
168     if (ret == 0)
169 	errx(1, "rk_getpwnam_r no user");
170 
171     ret = rk_getpwuid_r(0, &pwd, buf, sizeof(buf), &result);
172     if (ret)
173 	errx(1, "rk_getpwuid_r");
174     print_result(result);
175 
176     ret = rk_getpwuid_r(0, &pwd, buf, 1, &result);
177     if (ret == 0)
178 	errx(1, "rk_getpwuid_r too small buf");
179 
180     ret = rk_getpwuid_r(-1234, &pwd, buf, sizeof(buf), &result);
181     if (ret == 0)
182 	errx(1, "rk_getpwuid_r no user");
183     return 0;
184 }
185 
186 #endif
187