passwd.c revision 194093
1230557Sjimharris/*- 2230557Sjimharris * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru> 3230557Sjimharris * All rights reserved. 4230557Sjimharris * 5230557Sjimharris * Redistribution and use in source and binary forms, with or without 6230557Sjimharris * modification, are permitted provided that the following conditions 7230557Sjimharris * are met: 8230557Sjimharris * 1. Redistributions of source code must retain the above copyright 9230557Sjimharris * notice, this list of conditions and the following disclaimer. 10230557Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 11230557Sjimharris * notice, this list of conditions and the following disclaimer in the 12230557Sjimharris * documentation and/or other materials provided with the distribution. 13230557Sjimharris * 14230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15230557Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16230557Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17230557Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18230557Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19230557Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20230557Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21230557Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22230557Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23230557Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24230557Sjimharris * SUCH DAMAGE. 25230557Sjimharris * 26230557Sjimharris */ 27230557Sjimharris 28230557Sjimharris#include <sys/cdefs.h> 29230557Sjimharris__FBSDID("$FreeBSD: head/usr.sbin/nscd/agents/passwd.c 194093 2009-06-13 00:43:56Z des $"); 30230557Sjimharris 31230557Sjimharris#include <sys/types.h> 32230557Sjimharris 33230557Sjimharris#include <assert.h> 34230557Sjimharris#include <nsswitch.h> 35230557Sjimharris#include <pwd.h> 36230557Sjimharris#include <stdlib.h> 37230557Sjimharris#include <string.h> 38230557Sjimharris 39230557Sjimharris#include "../debug.h" 40230557Sjimharris#include "passwd.h" 41230557Sjimharris 42230557Sjimharrisstatic int passwd_marshal_func(struct passwd *, char *, size_t *); 43230557Sjimharrisstatic int passwd_lookup_func(const char *, size_t, char **, size_t *); 44230557Sjimharrisstatic void *passwd_mp_init_func(void); 45230557Sjimharrisstatic int passwd_mp_lookup_func(char **, size_t *, void *); 46230557Sjimharrisstatic void passwd_mp_destroy_func(void *mdata); 47230557Sjimharris 48230557Sjimharrisstatic int 49230557Sjimharrispasswd_marshal_func(struct passwd *pwd, char *buffer, size_t *buffer_size) 50230557Sjimharris{ 51230557Sjimharris char *p; 52230557Sjimharris struct passwd new_pwd; 53230557Sjimharris size_t desired_size, size; 54230557Sjimharris 55230557Sjimharris TRACE_IN(passwd_marshal_func); 56230557Sjimharris desired_size = sizeof(struct passwd) + sizeof(char *) + 57230557Sjimharris strlen(pwd->pw_name) + 1; 58230557Sjimharris if (pwd->pw_passwd != NULL) 59230557Sjimharris desired_size += strlen(pwd->pw_passwd) + 1; 60230557Sjimharris if (pwd->pw_class != NULL) 61230557Sjimharris desired_size += strlen(pwd->pw_class) + 1; 62230557Sjimharris if (pwd->pw_gecos != NULL) 63230557Sjimharris desired_size += strlen(pwd->pw_gecos) + 1; 64230557Sjimharris if (pwd->pw_dir != NULL) 65230557Sjimharris desired_size += strlen(pwd->pw_dir) + 1; 66230557Sjimharris if (pwd->pw_shell != NULL) 67230557Sjimharris desired_size += strlen(pwd->pw_shell) + 1; 68230557Sjimharris 69230557Sjimharris if ((*buffer_size < desired_size) || (buffer == NULL)) { 70230557Sjimharris *buffer_size = desired_size; 71230557Sjimharris TRACE_OUT(passwd_marshal_func); 72230557Sjimharris return (NS_RETURN); 73230557Sjimharris } 74230557Sjimharris 75230557Sjimharris memcpy(&new_pwd, pwd, sizeof(struct passwd)); 76230557Sjimharris memset(buffer, 0, desired_size); 77230557Sjimharris 78230557Sjimharris *buffer_size = desired_size; 79230557Sjimharris p = buffer + sizeof(struct passwd) + sizeof(char *); 80230557Sjimharris memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *)); 81230557Sjimharris 82230557Sjimharris if (new_pwd.pw_name != NULL) { 83230557Sjimharris size = strlen(new_pwd.pw_name); 84230557Sjimharris memcpy(p, new_pwd.pw_name, size); 85230557Sjimharris new_pwd.pw_name = p; 86230557Sjimharris p += size + 1; 87230557Sjimharris } 88230557Sjimharris 89230557Sjimharris if (new_pwd.pw_passwd != NULL) { 90230557Sjimharris size = strlen(new_pwd.pw_passwd); 91230557Sjimharris memcpy(p, new_pwd.pw_passwd, size); 92230557Sjimharris new_pwd.pw_passwd = p; 93230557Sjimharris p += size + 1; 94230557Sjimharris } 95230557Sjimharris 96230557Sjimharris if (new_pwd.pw_class != NULL) { 97230557Sjimharris size = strlen(new_pwd.pw_class); 98230557Sjimharris memcpy(p, new_pwd.pw_class, size); 99230557Sjimharris new_pwd.pw_class = p; 100230557Sjimharris p += size + 1; 101230557Sjimharris } 102230557Sjimharris 103230557Sjimharris if (new_pwd.pw_gecos != NULL) { 104230557Sjimharris size = strlen(new_pwd.pw_gecos); 105230557Sjimharris memcpy(p, new_pwd.pw_gecos, size); 106230557Sjimharris new_pwd.pw_gecos = p; 107230557Sjimharris p += size + 1; 108230557Sjimharris } 109230557Sjimharris 110230557Sjimharris if (new_pwd.pw_dir != NULL) { 111230557Sjimharris size = strlen(new_pwd.pw_dir); 112230557Sjimharris memcpy(p, new_pwd.pw_dir, size); 113230557Sjimharris new_pwd.pw_dir = p; 114230557Sjimharris p += size + 1; 115230557Sjimharris } 116230557Sjimharris 117230557Sjimharris if (new_pwd.pw_shell != NULL) { 118230557Sjimharris size = strlen(new_pwd.pw_shell); 119230557Sjimharris memcpy(p, new_pwd.pw_shell, size); 120230557Sjimharris new_pwd.pw_shell = p; 121230557Sjimharris p += size + 1; 122230557Sjimharris } 123230557Sjimharris 124230557Sjimharris memcpy(buffer, &new_pwd, sizeof(struct passwd)); 125230557Sjimharris TRACE_OUT(passwd_marshal_func); 126230557Sjimharris return (NS_SUCCESS); 127230557Sjimharris} 128230557Sjimharris 129230557Sjimharrisstatic int 130230557Sjimharrispasswd_lookup_func(const char *key, size_t key_size, char **buffer, 131230557Sjimharris size_t *buffer_size) 132230557Sjimharris{ 133230557Sjimharris enum nss_lookup_type lookup_type; 134230557Sjimharris char *login; 135230557Sjimharris size_t size; 136230557Sjimharris uid_t uid; 137230557Sjimharris 138230557Sjimharris struct passwd *result; 139230557Sjimharris 140230557Sjimharris TRACE_IN(passwd_lookup_func); 141230557Sjimharris assert(buffer != NULL); 142230557Sjimharris assert(buffer_size != NULL); 143230557Sjimharris 144230557Sjimharris if (key_size < sizeof(enum nss_lookup_type)) { 145230557Sjimharris TRACE_OUT(passwd_lookup_func); 146230557Sjimharris return (NS_UNAVAIL); 147230557Sjimharris } 148230557Sjimharris memcpy(&lookup_type, key, sizeof(enum nss_lookup_type)); 149230557Sjimharris 150230557Sjimharris switch (lookup_type) { 151230557Sjimharris case nss_lt_name: 152230557Sjimharris size = key_size - sizeof(enum nss_lookup_type) + 1; 153230557Sjimharris login = (char *)calloc(1, size); 154230557Sjimharris assert(login != NULL); 155230557Sjimharris memcpy(login, key + sizeof(enum nss_lookup_type), size - 1); 156230557Sjimharris break; 157230557Sjimharris case nss_lt_id: 158230557Sjimharris if (key_size < sizeof(enum nss_lookup_type) + 159230557Sjimharris sizeof(uid_t)) { 160230557Sjimharris TRACE_OUT(passwd_lookup_func); 161230557Sjimharris return (NS_UNAVAIL); 162230557Sjimharris } 163230557Sjimharris 164230557Sjimharris memcpy(&uid, key + sizeof(enum nss_lookup_type), sizeof(uid_t)); 165230557Sjimharris break; 166230557Sjimharris default: 167230557Sjimharris TRACE_OUT(passwd_lookup_func); 168230557Sjimharris return (NS_UNAVAIL); 169230557Sjimharris } 170230557Sjimharris 171230557Sjimharris switch (lookup_type) { 172230557Sjimharris case nss_lt_name: 173230557Sjimharris result = getpwnam(login); 174230557Sjimharris free(login); 175230557Sjimharris break; 176230557Sjimharris case nss_lt_id: 177230557Sjimharris result = getpwuid(uid); 178230557Sjimharris break; 179230557Sjimharris default: 180230557Sjimharris /* SHOULD NOT BE REACHED */ 181230557Sjimharris break; 182230557Sjimharris } 183230557Sjimharris 184230557Sjimharris if (result != NULL) { 185230557Sjimharris passwd_marshal_func(result, NULL, buffer_size); 186230557Sjimharris *buffer = (char *)malloc(*buffer_size); 187230557Sjimharris assert(*buffer != NULL); 188230557Sjimharris passwd_marshal_func(result, *buffer, buffer_size); 189230557Sjimharris } 190230557Sjimharris 191230557Sjimharris TRACE_OUT(passwd_lookup_func); 192230557Sjimharris return (result == NULL ? NS_NOTFOUND : NS_SUCCESS); 193230557Sjimharris} 194230557Sjimharris 195230557Sjimharrisstatic void * 196230557Sjimharrispasswd_mp_init_func(void) 197230557Sjimharris{ 198230557Sjimharris TRACE_IN(passwd_mp_init_func); 199230557Sjimharris setpwent(); 200230557Sjimharris TRACE_OUT(passwd_mp_init_func); 201230557Sjimharris 202230557Sjimharris return (NULL); 203230557Sjimharris} 204230557Sjimharris 205230557Sjimharrisstatic int 206230557Sjimharrispasswd_mp_lookup_func(char **buffer, size_t *buffer_size, void *mdata) 207230557Sjimharris{ 208230557Sjimharris struct passwd *result; 209230557Sjimharris 210230557Sjimharris TRACE_IN(passwd_mp_lookup_func); 211230557Sjimharris result = getpwent(); 212230557Sjimharris if (result != NULL) { 213230557Sjimharris passwd_marshal_func(result, NULL, buffer_size); 214230557Sjimharris *buffer = (char *)malloc(*buffer_size); 215230557Sjimharris assert(*buffer != NULL); 216230557Sjimharris passwd_marshal_func(result, *buffer, buffer_size); 217230557Sjimharris } 218230557Sjimharris 219230557Sjimharris TRACE_OUT(passwd_mp_lookup_func); 220230557Sjimharris return (result == NULL ? NS_NOTFOUND : NS_SUCCESS); 221230557Sjimharris} 222230557Sjimharris 223230557Sjimharrisstatic void 224230557Sjimharrispasswd_mp_destroy_func(void *mdata) 225230557Sjimharris{ 226230557Sjimharris TRACE_IN(passwd_mp_destroy_func); 227230557Sjimharris TRACE_OUT(passwd_mp_destroy_func); 228230557Sjimharris} 229230557Sjimharris 230230557Sjimharrisstruct agent * 231230557Sjimharrisinit_passwd_agent(void) 232230557Sjimharris{ 233230557Sjimharris struct common_agent *retval; 234230557Sjimharris 235230557Sjimharris TRACE_IN(init_passwd_agent); 236230557Sjimharris retval = (struct common_agent *)calloc(1, sizeof(struct common_agent)); 237230557Sjimharris assert(retval != NULL); 238230557Sjimharris 239230557Sjimharris retval->parent.name = strdup("passwd"); 240230557Sjimharris assert(retval->parent.name != NULL); 241230557Sjimharris 242230557Sjimharris retval->parent.type = COMMON_AGENT; 243230557Sjimharris retval->lookup_func = passwd_lookup_func; 244230557Sjimharris 245230557Sjimharris TRACE_OUT(init_passwd_agent); 246230557Sjimharris return ((struct agent *)retval); 247230557Sjimharris} 248230557Sjimharris 249230557Sjimharrisstruct agent * 250230557Sjimharrisinit_passwd_mp_agent(void) 251230557Sjimharris{ 252230557Sjimharris struct multipart_agent *retval; 253230557Sjimharris 254230557Sjimharris TRACE_IN(init_passwd_mp_agent); 255230557Sjimharris retval = (struct multipart_agent *)calloc(1, 256230557Sjimharris sizeof(struct multipart_agent)); 257230557Sjimharris assert(retval != NULL); 258230557Sjimharris 259230557Sjimharris retval->parent.name = strdup("passwd"); 260230557Sjimharris retval->parent.type = MULTIPART_AGENT; 261230557Sjimharris retval->mp_init_func = passwd_mp_init_func; 262230557Sjimharris retval->mp_lookup_func = passwd_mp_lookup_func; 263230557Sjimharris retval->mp_destroy_func = passwd_mp_destroy_func; 264230557Sjimharris assert(retval->parent.name != NULL); 265230557Sjimharris 266230557Sjimharris TRACE_OUT(init_passwd_mp_agent); 267230557Sjimharris return ((struct agent *)retval); 268230557Sjimharris} 269230557Sjimharris