1 /*
2 ** Copyright 1998 - 2002 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 #include <sys/types.h>
10 #if HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <grp.h>
17 #include <pwd.h>
18 #include <errno.h>
19
20 #include "numlib.h"
21
22
libmail_changegroup(gid_t gid)23 void libmail_changegroup(gid_t gid)
24 {
25 if ( setgid(gid))
26 {
27 perror("setgid");
28 exit(1);
29 }
30
31 #if HAVE_SETGROUPS
32 if ( getuid() == 0 && setgroups(1, &gid) )
33 {
34 perror("setgroups");
35 exit(1);
36 }
37 #endif
38 }
39
libmail_changeuidgid(uid_t uid,gid_t gid)40 void libmail_changeuidgid(uid_t uid, gid_t gid)
41 {
42 libmail_changegroup(gid);
43 if ( setuid(uid))
44 {
45 perror("setuid");
46 exit(1);
47 }
48 }
49
50 /**
51 * Obtain the uid associated to uname and, optionally, the user primary gid
52 */
libmail_getuid(const char * uname,gid_t * pw_gid)53 uid_t libmail_getuid(const char *uname, gid_t *pw_gid)
54 {
55 size_t bufsize;
56 char *buf;
57 struct passwd pwbuf;
58 struct passwd *pw;
59
60 /*
61 ** uname might be a pointer returned from a previous called to getpw(),
62 ** and libc has a problem getting it back.
63 */
64 char *p=malloc(strlen(uname)+1);
65
66 if (!p)
67 {
68 perror("malloc");
69 exit(1);
70 }
71 strcpy(p, uname);
72
73 #ifdef _SC_GETGR_R_SIZE_MAX
74 bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
75 if (bufsize == -1) /* Value was indeterminate */
76 {
77 #endif
78 bufsize = 16384; /* Should be more than enough */
79 }
80
81 buf = malloc(bufsize);
82 if (buf == NULL)
83 {
84 perror("malloc");
85 exit(1);
86 }
87
88
89 errno=ENOENT;
90
91 getpwnam_r(p, &pwbuf, buf, bufsize, &pw);
92
93 free(buf);
94
95 if (pw == 0)
96 {
97 free(p);
98 perror("getpwnam");
99 exit(1);
100 }
101 free(p);
102
103 if ( pw_gid ) *pw_gid = pw->pw_gid;
104
105 return pw->pw_uid;
106 }
107
libmail_changeusername(const char * uname,const gid_t * forcegrp)108 void libmail_changeusername(const char *uname, const gid_t *forcegrp)
109 {
110 uid_t changeuid;
111 gid_t changegid;
112
113 changeuid=libmail_getuid(uname, &changegid);
114
115 if ( forcegrp ) changegid= *forcegrp;
116
117 if ( setgid( changegid ))
118 {
119 perror("setgid");
120 exit(1);
121 }
122
123 #if HAVE_INITGROUPS
124 if ( getuid() == 0 && initgroups(uname, changegid) )
125 {
126 perror("initgroups");
127 exit(1);
128 }
129 #else
130 #if HAVE_SETGROUPS
131 if ( getuid() == 0 && setgroups(1, &changegid) )
132 {
133 perror("setgroups");
134 exit(1);
135 }
136 #endif
137 #endif
138
139 if (setuid(changeuid))
140 {
141 perror("setuid");
142 exit(1);
143 }
144 }
145
libmail_getgid(const char * gname)146 gid_t libmail_getgid(const char *gname)
147 {
148 gid_t g;
149 struct group grp;
150 struct group *result;
151 char *buf;
152 size_t bufsize;
153 int s;
154 char *p=malloc(strlen(gname)+1);
155
156 if (!p)
157 {
158 perror("malloc");
159 exit(1);
160 }
161 strcpy(p, gname);
162
163 #ifdef _SC_GETGR_R_SIZE_MAX
164 bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
165 if (bufsize == -1) /* Value was indeterminate */
166 #endif
167 {
168 bufsize = 16384; /* Should be more than enough */
169 }
170
171 buf = malloc(bufsize);
172 if (buf == NULL)
173 {
174 perror("malloc");
175 exit(1);
176 }
177
178 s = getgrnam_r(p, &grp, buf, bufsize, &result);
179 free(p);
180
181 if (result == NULL)
182 {
183 if (s == 0)
184 {
185 fprintf(stderr, "CRIT: Group %s not found\n", gname);
186 }
187 else
188 {
189 errno = s;
190 perror("getpwnam_r");
191 }
192 exit(1);
193 }
194
195 g = grp.gr_gid;
196 free(buf);
197
198 return g;
199 }
200