1 /* Copyright 1988, 1996 by the Massachusetts Institute of Technology.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions
5  * are met:
6  *
7  * * Redistributions of source code must retain the above copyright
8  *   notice, this list of conditions and the following disclaimer.
9  *
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in
12  *   the documentation and/or other materials provided with the
13  *   distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26  * OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /* This file is part of the Hesiod library.  It implements
30  * hesiod_getpwnam and hesiod_getpwuid, for retrieving passwd
31  * information about a user.
32  */
33 
34 static const char rcsid[] = "$Id: hespwnam.c,v 1.16 2002-04-03 21:40:55 ghudson Exp $";
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <pwd.h>
40 #include <errno.h>
41 #include <netdb.h>
42 #include "hesiod.h"
43 #include "config.h"
44 
45 extern char **hesiod__uidresolve(void *context, const char *uidstr);
46 
47 static struct passwd *getpwcommon(void *context, const char *arg, int which);
48 static char *next_field(char *ptr);
49 
hesiod_getpwnam(void * context,const char * name)50 struct passwd *hesiod_getpwnam(void *context, const char *name)
51 {
52   return getpwcommon(context, name, 0);
53 }
54 
hesiod_getpwuid(void * context,uid_t uid)55 struct passwd *hesiod_getpwuid(void *context, uid_t uid)
56 {
57   char uidstr[16];
58 
59   sprintf(uidstr, "%u", (unsigned int)uid);
60   return getpwcommon(context, uidstr, 1);
61 }
62 
hesiod_free_passwd(void * context,struct passwd * pw)63 void hesiod_free_passwd(void *context, struct passwd *pw)
64 {
65   free(pw->pw_name);
66   free(pw);
67 }
68 
getpwcommon(void * context,const char * arg,int which)69 static struct passwd *getpwcommon(void *context, const char *arg, int which)
70 {
71   char *p, **list;
72   struct passwd *pw;
73 
74   /* Get the response and copy the first entry into a buffer. */
75   list = hesiod_resolve(context, arg, which ? "uid" : "passwd");
76   if (!list)
77     return NULL;
78   p = malloc(strlen(*list) + 1);
79   if (!p)
80     {
81       hesiod_free_list(context, list);
82       errno = ENOMEM;
83       return NULL;
84     }
85   strcpy(p, *list);
86   hesiod_free_list(context, list);
87 
88   /* Allocate memory for the result. */
89   pw = (struct passwd *) malloc(sizeof(struct passwd));
90   if (!pw)
91     {
92       free(p);
93       errno = ENOMEM;
94       return NULL;
95     }
96 
97   /* Split up buf into fields. */
98   pw->pw_name = p;
99   p = next_field(p);
100   pw->pw_passwd = p;
101   p = next_field(p);
102   pw->pw_uid = atoi(p);
103   p = next_field(p);
104   pw->pw_gid = atoi(p);
105   p = next_field(p);
106   pw->pw_gecos = p;
107   p = next_field(p);
108   pw->pw_dir = p;
109   p = next_field(p);
110   pw->pw_shell = p;
111   while (*p && *p != '\n')
112     p++;
113   *p = 0;
114 
115 #ifdef HAVE_PW_QUOTA
116   pw->pw_quota = 0;
117 #endif
118 #ifdef HAVE_PW_COMMENT
119   pw->pw_comment = "";
120 #endif
121 #ifdef HAVE_PW_CLASS
122   pw->pw_class = "";
123 #endif
124 #ifdef HAVE_PW_CHANGE
125   pw->pw_change = 0;
126 #endif
127 #ifdef HAVE_PW_EXPIRE
128   pw->pw_expire = 0;
129 #endif
130 
131   return pw;
132 }
133 
134 /* Null-terminate the current colon-separated field in the passwd entry and
135  * return a pointer to the beginning of the next one.
136  */
next_field(char * ptr)137 static char *next_field(char *ptr)
138 {
139   while (*ptr && *ptr != '\n' && *ptr != ':')
140     ptr++;
141   if (*ptr)
142     *ptr++ = '\0';
143   return ptr;
144 }
145