1 /*- 2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/types.h> 32 33 #include <assert.h> 34 #include <nsswitch.h> 35 #include <pwd.h> 36 #include <stdlib.h> 37 #include <string.h> 38 39 #include "../debug.h" 40 #include "passwd.h" 41 42 static int passwd_marshal_func(struct passwd *, char *, size_t *); 43 static int passwd_lookup_func(const char *, size_t, char **, size_t *); 44 static void *passwd_mp_init_func(void); 45 static int passwd_mp_lookup_func(char **, size_t *, void *); 46 static void passwd_mp_destroy_func(void *mdata); 47 48 static int 49 passwd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size) 50 { 51 char *p; 52 struct passwd new_pwd; 53 size_t desired_size, size; 54 55 TRACE_IN(passwd_marshal_func); 56 desired_size = sizeof(struct passwd) + sizeof(char *) + 57 strlen(pwd->pw_name) + 1; 58 if (pwd->pw_passwd != NULL) 59 desired_size += strlen(pwd->pw_passwd) + 1; 60 if (pwd->pw_class != NULL) 61 desired_size += strlen(pwd->pw_class) + 1; 62 if (pwd->pw_gecos != NULL) 63 desired_size += strlen(pwd->pw_gecos) + 1; 64 if (pwd->pw_dir != NULL) 65 desired_size += strlen(pwd->pw_dir) + 1; 66 if (pwd->pw_shell != NULL) 67 desired_size += strlen(pwd->pw_shell) + 1; 68 69 if ((*buffer_size < desired_size) || (buffer == NULL)) { 70 *buffer_size = desired_size; 71 TRACE_OUT(passwd_marshal_func); 72 return (NS_RETURN); 73 } 74 75 memcpy(&new_pwd, pwd, sizeof(struct passwd)); 76 memset(buffer, 0, desired_size); 77 78 *buffer_size = desired_size; 79 p = buffer + sizeof(struct passwd) + sizeof(char *); 80 memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *)); 81 82 if (new_pwd.pw_name != NULL) { 83 size = strlen(new_pwd.pw_name); 84 memcpy(p, new_pwd.pw_name, size); 85 new_pwd.pw_name = p; 86 p += size + 1; 87 } 88 89 if (new_pwd.pw_passwd != NULL) { 90 size = strlen(new_pwd.pw_passwd); 91 memcpy(p, new_pwd.pw_passwd, size); 92 new_pwd.pw_passwd = p; 93 p += size + 1; 94 } 95 96 if (new_pwd.pw_class != NULL) { 97 size = strlen(new_pwd.pw_class); 98 memcpy(p, new_pwd.pw_class, size); 99 new_pwd.pw_class = p; 100 p += size + 1; 101 } 102 103 if (new_pwd.pw_gecos != NULL) { 104 size = strlen(new_pwd.pw_gecos); 105 memcpy(p, new_pwd.pw_gecos, size); 106 new_pwd.pw_gecos = p; 107 p += size + 1; 108 } 109 110 if (new_pwd.pw_dir != NULL) { 111 size = strlen(new_pwd.pw_dir); 112 memcpy(p, new_pwd.pw_dir, size); 113 new_pwd.pw_dir = p; 114 p += size + 1; 115 } 116 117 if (new_pwd.pw_shell != NULL) { 118 size = strlen(new_pwd.pw_shell); 119 memcpy(p, new_pwd.pw_shell, size); 120 new_pwd.pw_shell = p; 121 p += size + 1; 122 } 123 124 memcpy(buffer, &new_pwd, sizeof(struct passwd)); 125 TRACE_OUT(passwd_marshal_func); 126 return (NS_SUCCESS); 127 } 128 129 static int 130 passwd_lookup_func(const char *key, size_t key_size, char **buffer, 131 size_t *buffer_size) 132 { 133 enum nss_lookup_type lookup_type; 134 char *login; 135 size_t size; 136 uid_t uid; 137 138 struct passwd *result; 139 140 TRACE_IN(passwd_lookup_func); 141 assert(buffer != NULL); 142 assert(buffer_size != NULL); 143 144 if (key_size < sizeof(enum nss_lookup_type)) { 145 TRACE_OUT(passwd_lookup_func); 146 return (NS_UNAVAIL); 147 } 148 memcpy(&lookup_type, key, sizeof(enum nss_lookup_type)); 149 150 switch (lookup_type) { 151 case nss_lt_name: 152 size = key_size - sizeof(enum nss_lookup_type) + 1; 153 login = calloc(1, size); 154 assert(login != NULL); 155 memcpy(login, key + sizeof(enum nss_lookup_type), size - 1); 156 break; 157 case nss_lt_id: 158 if (key_size < sizeof(enum nss_lookup_type) + 159 sizeof(uid_t)) { 160 TRACE_OUT(passwd_lookup_func); 161 return (NS_UNAVAIL); 162 } 163 164 memcpy(&uid, key + sizeof(enum nss_lookup_type), sizeof(uid_t)); 165 break; 166 default: 167 TRACE_OUT(passwd_lookup_func); 168 return (NS_UNAVAIL); 169 } 170 171 switch (lookup_type) { 172 case nss_lt_name: 173 result = getpwnam(login); 174 free(login); 175 break; 176 case nss_lt_id: 177 result = getpwuid(uid); 178 break; 179 default: 180 /* SHOULD NOT BE REACHED */ 181 break; 182 } 183 184 if (result != NULL) { 185 passwd_marshal_func(result, NULL, buffer_size); 186 *buffer = malloc(*buffer_size); 187 assert(*buffer != NULL); 188 passwd_marshal_func(result, *buffer, buffer_size); 189 } 190 191 TRACE_OUT(passwd_lookup_func); 192 return (result == NULL ? NS_NOTFOUND : NS_SUCCESS); 193 } 194 195 static void * 196 passwd_mp_init_func(void) 197 { 198 TRACE_IN(passwd_mp_init_func); 199 setpwent(); 200 TRACE_OUT(passwd_mp_init_func); 201 202 return (NULL); 203 } 204 205 static int 206 passwd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata) 207 { 208 struct passwd *result; 209 210 TRACE_IN(passwd_mp_lookup_func); 211 result = getpwent(); 212 if (result != NULL) { 213 passwd_marshal_func(result, NULL, buffer_size); 214 *buffer = malloc(*buffer_size); 215 assert(*buffer != NULL); 216 passwd_marshal_func(result, *buffer, buffer_size); 217 } 218 219 TRACE_OUT(passwd_mp_lookup_func); 220 return (result == NULL ? NS_NOTFOUND : NS_SUCCESS); 221 } 222 223 static void 224 passwd_mp_destroy_func(void *mdata) 225 { 226 TRACE_IN(passwd_mp_destroy_func); 227 TRACE_OUT(passwd_mp_destroy_func); 228 } 229 230 struct agent * 231 init_passwd_agent(void) 232 { 233 struct common_agent *retval; 234 235 TRACE_IN(init_passwd_agent); 236 retval = calloc(1, sizeof(*retval)); 237 assert(retval != NULL); 238 239 retval->parent.name = strdup("passwd"); 240 assert(retval->parent.name != NULL); 241 242 retval->parent.type = COMMON_AGENT; 243 retval->lookup_func = passwd_lookup_func; 244 245 TRACE_OUT(init_passwd_agent); 246 return ((struct agent *)retval); 247 } 248 249 struct agent * 250 init_passwd_mp_agent(void) 251 { 252 struct multipart_agent *retval; 253 254 TRACE_IN(init_passwd_mp_agent); 255 retval = calloc(1, 256 sizeof(*retval)); 257 assert(retval != NULL); 258 259 retval->parent.name = strdup("passwd"); 260 retval->parent.type = MULTIPART_AGENT; 261 retval->mp_init_func = passwd_mp_init_func; 262 retval->mp_lookup_func = passwd_mp_lookup_func; 263 retval->mp_destroy_func = passwd_mp_destroy_func; 264 assert(retval->parent.name != NULL); 265 266 TRACE_OUT(init_passwd_mp_agent); 267 return ((struct agent *)retval); 268 } 269