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