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