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/types.h> 29 30 #include <assert.h> 31 #include <nsswitch.h> 32 #include <pwd.h> 33 #include <stdlib.h> 34 #include <string.h> 35 36 #include "../debug.h" 37 #include "passwd.h" 38 39 static int passwd_marshal_func(struct passwd *, char *, size_t *); 40 static int passwd_lookup_func(const char *, size_t, char **, size_t *); 41 static void *passwd_mp_init_func(void); 42 static int passwd_mp_lookup_func(char **, size_t *, void *); 43 static void passwd_mp_destroy_func(void *mdata); 44 45 static int 46 passwd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size) 47 { 48 char *p; 49 struct passwd new_pwd; 50 size_t desired_size, size; 51 52 TRACE_IN(passwd_marshal_func); 53 desired_size = sizeof(struct passwd) + sizeof(char *) + 54 strlen(pwd->pw_name) + 1; 55 if (pwd->pw_passwd != NULL) 56 desired_size += strlen(pwd->pw_passwd) + 1; 57 if (pwd->pw_class != NULL) 58 desired_size += strlen(pwd->pw_class) + 1; 59 if (pwd->pw_gecos != NULL) 60 desired_size += strlen(pwd->pw_gecos) + 1; 61 if (pwd->pw_dir != NULL) 62 desired_size += strlen(pwd->pw_dir) + 1; 63 if (pwd->pw_shell != NULL) 64 desired_size += strlen(pwd->pw_shell) + 1; 65 66 if ((*buffer_size < desired_size) || (buffer == NULL)) { 67 *buffer_size = desired_size; 68 TRACE_OUT(passwd_marshal_func); 69 return (NS_RETURN); 70 } 71 72 memcpy(&new_pwd, pwd, sizeof(struct passwd)); 73 memset(buffer, 0, desired_size); 74 75 *buffer_size = desired_size; 76 p = buffer + sizeof(struct passwd) + sizeof(char *); 77 memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *)); 78 79 if (new_pwd.pw_name != NULL) { 80 size = strlen(new_pwd.pw_name); 81 memcpy(p, new_pwd.pw_name, size); 82 new_pwd.pw_name = p; 83 p += size + 1; 84 } 85 86 if (new_pwd.pw_passwd != NULL) { 87 size = strlen(new_pwd.pw_passwd); 88 memcpy(p, new_pwd.pw_passwd, size); 89 new_pwd.pw_passwd = p; 90 p += size + 1; 91 } 92 93 if (new_pwd.pw_class != NULL) { 94 size = strlen(new_pwd.pw_class); 95 memcpy(p, new_pwd.pw_class, size); 96 new_pwd.pw_class = p; 97 p += size + 1; 98 } 99 100 if (new_pwd.pw_gecos != NULL) { 101 size = strlen(new_pwd.pw_gecos); 102 memcpy(p, new_pwd.pw_gecos, size); 103 new_pwd.pw_gecos = p; 104 p += size + 1; 105 } 106 107 if (new_pwd.pw_dir != NULL) { 108 size = strlen(new_pwd.pw_dir); 109 memcpy(p, new_pwd.pw_dir, size); 110 new_pwd.pw_dir = p; 111 p += size + 1; 112 } 113 114 if (new_pwd.pw_shell != NULL) { 115 size = strlen(new_pwd.pw_shell); 116 memcpy(p, new_pwd.pw_shell, size); 117 new_pwd.pw_shell = p; 118 p += size + 1; 119 } 120 121 memcpy(buffer, &new_pwd, sizeof(struct passwd)); 122 TRACE_OUT(passwd_marshal_func); 123 return (NS_SUCCESS); 124 } 125 126 static int 127 passwd_lookup_func(const char *key, size_t key_size, char **buffer, 128 size_t *buffer_size) 129 { 130 enum nss_lookup_type lookup_type; 131 char *login; 132 size_t size; 133 uid_t uid; 134 135 struct passwd *result; 136 137 TRACE_IN(passwd_lookup_func); 138 assert(buffer != NULL); 139 assert(buffer_size != NULL); 140 141 if (key_size < sizeof(enum nss_lookup_type)) { 142 TRACE_OUT(passwd_lookup_func); 143 return (NS_UNAVAIL); 144 } 145 memcpy(&lookup_type, key, sizeof(enum nss_lookup_type)); 146 147 switch (lookup_type) { 148 case nss_lt_name: 149 size = key_size - sizeof(enum nss_lookup_type) + 1; 150 login = calloc(1, size); 151 assert(login != NULL); 152 memcpy(login, key + sizeof(enum nss_lookup_type), size - 1); 153 break; 154 case nss_lt_id: 155 if (key_size < sizeof(enum nss_lookup_type) + 156 sizeof(uid_t)) { 157 TRACE_OUT(passwd_lookup_func); 158 return (NS_UNAVAIL); 159 } 160 161 memcpy(&uid, key + sizeof(enum nss_lookup_type), sizeof(uid_t)); 162 break; 163 default: 164 TRACE_OUT(passwd_lookup_func); 165 return (NS_UNAVAIL); 166 } 167 168 switch (lookup_type) { 169 case nss_lt_name: 170 result = getpwnam(login); 171 free(login); 172 break; 173 case nss_lt_id: 174 result = getpwuid(uid); 175 break; 176 default: 177 /* SHOULD NOT BE REACHED */ 178 break; 179 } 180 181 if (result != NULL) { 182 passwd_marshal_func(result, NULL, buffer_size); 183 *buffer = malloc(*buffer_size); 184 assert(*buffer != NULL); 185 passwd_marshal_func(result, *buffer, buffer_size); 186 } 187 188 TRACE_OUT(passwd_lookup_func); 189 return (result == NULL ? NS_NOTFOUND : NS_SUCCESS); 190 } 191 192 static void * 193 passwd_mp_init_func(void) 194 { 195 TRACE_IN(passwd_mp_init_func); 196 setpwent(); 197 TRACE_OUT(passwd_mp_init_func); 198 199 return (NULL); 200 } 201 202 static int 203 passwd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata) 204 { 205 struct passwd *result; 206 207 TRACE_IN(passwd_mp_lookup_func); 208 result = getpwent(); 209 if (result != NULL) { 210 passwd_marshal_func(result, NULL, buffer_size); 211 *buffer = malloc(*buffer_size); 212 assert(*buffer != NULL); 213 passwd_marshal_func(result, *buffer, buffer_size); 214 } 215 216 TRACE_OUT(passwd_mp_lookup_func); 217 return (result == NULL ? NS_NOTFOUND : NS_SUCCESS); 218 } 219 220 static void 221 passwd_mp_destroy_func(void *mdata) 222 { 223 TRACE_IN(passwd_mp_destroy_func); 224 TRACE_OUT(passwd_mp_destroy_func); 225 } 226 227 struct agent * 228 init_passwd_agent(void) 229 { 230 struct common_agent *retval; 231 232 TRACE_IN(init_passwd_agent); 233 retval = calloc(1, sizeof(*retval)); 234 assert(retval != NULL); 235 236 retval->parent.name = strdup("passwd"); 237 assert(retval->parent.name != NULL); 238 239 retval->parent.type = COMMON_AGENT; 240 retval->lookup_func = passwd_lookup_func; 241 242 TRACE_OUT(init_passwd_agent); 243 return ((struct agent *)retval); 244 } 245 246 struct agent * 247 init_passwd_mp_agent(void) 248 { 249 struct multipart_agent *retval; 250 251 TRACE_IN(init_passwd_mp_agent); 252 retval = calloc(1, 253 sizeof(*retval)); 254 assert(retval != NULL); 255 256 retval->parent.name = strdup("passwd"); 257 retval->parent.type = MULTIPART_AGENT; 258 retval->mp_init_func = passwd_mp_init_func; 259 retval->mp_lookup_func = passwd_mp_lookup_func; 260 retval->mp_destroy_func = passwd_mp_destroy_func; 261 assert(retval->parent.name != NULL); 262 263 TRACE_OUT(init_passwd_mp_agent); 264 return ((struct agent *)retval); 265 } 266