userinfo.c revision 251886
1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_strings.h" 18#include "apr_portable.h" 19#include "apr_user.h" 20#include "apr_private.h" 21#ifdef HAVE_PWD_H 22#include <pwd.h> 23#endif 24#if APR_HAVE_SYS_TYPES_H 25#include <sys/types.h> 26#endif 27#if APR_HAVE_UNISTD_H 28#include <unistd.h> /* for _POSIX_THREAD_SAFE_FUNCTIONS */ 29#endif 30#define APR_WANT_MEMFUNC 31#include "apr_want.h" 32 33#define PWBUF_SIZE 2048 34 35static apr_status_t getpwnam_safe(const char *username, 36 struct passwd *pw, 37 char pwbuf[PWBUF_SIZE]) 38{ 39 struct passwd *pwptr; 40#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) 41 apr_status_t rv; 42 43 /* POSIX defines getpwnam_r() et al to return the error number 44 * rather than set errno, and requires pwptr to be set to NULL if 45 * the entry is not found, imply that "not found" is not an error 46 * condition; some implementations do return 0 with pwptr set to 47 * NULL. */ 48 rv = getpwnam_r(username, pw, pwbuf, PWBUF_SIZE, &pwptr); 49 if (rv) { 50 return rv; 51 } 52 if (pwptr == NULL) { 53 return APR_ENOENT; 54 } 55#else 56 /* Some platforms (e.g. FreeBSD 4.x) do not set errno on NULL "not 57 * found" return values for the non-threadsafe function either. */ 58 errno = 0; 59 if ((pwptr = getpwnam(username)) != NULL) { 60 memcpy(pw, pwptr, sizeof *pw); 61 } 62 else { 63 return errno ? errno : APR_ENOENT; 64 } 65#endif 66 return APR_SUCCESS; 67} 68 69APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname, 70 const char *username, 71 apr_pool_t *p) 72{ 73 struct passwd pw; 74 char pwbuf[PWBUF_SIZE]; 75 apr_status_t rv; 76 77 if ((rv = getpwnam_safe(username, &pw, pwbuf)) != APR_SUCCESS) 78 return rv; 79 80#ifdef OS2 81 /* Need to manually add user name for OS/2 */ 82 *dirname = apr_pstrcat(p, pw.pw_dir, pw.pw_name, NULL); 83#else 84 *dirname = apr_pstrdup(p, pw.pw_dir); 85#endif 86 return APR_SUCCESS; 87} 88 89 90 91APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid, 92 apr_gid_t *gid, 93 apr_pool_t *p) 94{ 95 *uid = getuid(); 96 *gid = getgid(); 97 98 return APR_SUCCESS; 99} 100 101 102 103 104APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid, 105 const char *username, apr_pool_t *p) 106{ 107 struct passwd pw; 108 char pwbuf[PWBUF_SIZE]; 109 apr_status_t rv; 110 111 if ((rv = getpwnam_safe(username, &pw, pwbuf)) != APR_SUCCESS) 112 return rv; 113 114 *uid = pw.pw_uid; 115 *gid = pw.pw_gid; 116 117 return APR_SUCCESS; 118} 119 120APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid, 121 apr_pool_t *p) 122{ 123 struct passwd *pw; 124#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) 125 struct passwd pwd; 126 char pwbuf[PWBUF_SIZE]; 127 apr_status_t rv; 128 129 rv = getpwuid_r(userid, &pwd, pwbuf, sizeof(pwbuf), &pw); 130 if (rv) { 131 return rv; 132 } 133 134 if (pw == NULL) { 135 return APR_ENOENT; 136 } 137 138#else 139 errno = 0; 140 if ((pw = getpwuid(userid)) == NULL) { 141 return errno ? errno : APR_ENOENT; 142 } 143#endif 144 *username = apr_pstrdup(p, pw->pw_name); 145 return APR_SUCCESS; 146} 147