libroot_debug: Merge guarded heap into libroot_debug.
[haiku.git] / src / system / libroot / posix / shadow.cpp
blob5f3d32b99498d75486821b1f846059d4f36e2333
1 /*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <shadow.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <unistd.h>
12 #include <new>
14 #include <OS.h>
16 #include <AutoDeleter.h>
17 #include <errno_private.h>
18 #include <libroot_private.h>
19 #include <RegistrarDefs.h>
20 #include <user_group.h>
22 #include <util/KMessage.h>
25 using BPrivate::UserGroupLocker;
26 using BPrivate::relocate_pointer;
29 static KMessage sShadowPwdDBReply;
30 static spwd** sShadowPwdEntries = NULL;
31 static size_t sShadowPwdEntryCount = 0;
32 static size_t sIterationIndex = 0;
34 static struct spwd sShadowPwdBuffer;
35 static char sShadowPwdStringBuffer[MAX_SHADOW_PWD_BUFFER_SIZE];
38 static status_t
39 init_shadow_pwd_db()
41 if (sShadowPwdEntries != NULL)
42 return B_OK;
44 // ask the registrar
45 KMessage message(BPrivate::B_REG_GET_SHADOW_PASSWD_DB);
46 status_t error = BPrivate::send_authentication_request_to_registrar(message,
47 sShadowPwdDBReply);
48 if (error != B_OK)
49 return error;
51 // unpack the reply
52 int32 count;
53 spwd** entries;
54 int32 numBytes;
55 if ((error = sShadowPwdDBReply.FindInt32("count", &count)) != B_OK
56 || (error = sShadowPwdDBReply.FindData("entries", B_RAW_TYPE,
57 (const void**)&entries, &numBytes)) != B_OK) {
58 return error;
61 // relocate the entries
62 addr_t baseAddress = (addr_t)entries;
63 for (int32 i = 0; i < count; i++) {
64 spwd* entry = relocate_pointer(baseAddress, entries[i]);
65 relocate_pointer(baseAddress, entry->sp_namp);
66 relocate_pointer(baseAddress, entry->sp_pwdp);
69 sShadowPwdEntries = entries;
70 sShadowPwdEntryCount = count;
72 return B_OK;
76 // #pragma mark -
79 struct spwd*
80 getspent(void)
82 struct spwd* result = NULL;
83 int status = getspent_r(&sShadowPwdBuffer, sShadowPwdStringBuffer,
84 sizeof(sShadowPwdStringBuffer), &result);
85 if (status != 0)
86 __set_errno(status);
87 return result;
91 int
92 getspent_r(struct spwd* spwd, char* buffer, size_t bufferSize,
93 struct spwd** _result)
95 UserGroupLocker _;
97 int status = B_NO_MEMORY;
99 *_result = NULL;
101 if ((status = init_shadow_pwd_db()) == B_OK) {
102 if (sIterationIndex >= sShadowPwdEntryCount)
103 return ENOENT;
105 status = BPrivate::copy_shadow_pwd_to_buffer(
106 sShadowPwdEntries[sIterationIndex], spwd, buffer, bufferSize);
108 if (status == B_OK) {
109 sIterationIndex++;
110 *_result = spwd;
114 return status;
118 void
119 setspent(void)
121 UserGroupLocker _;
123 sIterationIndex = 0;
127 void
128 endspent(void)
130 UserGroupLocker locker;
132 sShadowPwdDBReply.Unset();
133 sShadowPwdEntries = NULL;
134 sShadowPwdEntryCount = 0;
135 sIterationIndex = 0;
139 struct spwd *
140 getspnam(const char *name)
142 struct spwd* result = NULL;
143 int status = getspnam_r(name, &sShadowPwdBuffer, sShadowPwdStringBuffer,
144 sizeof(sShadowPwdStringBuffer), &result);
145 if (status != 0)
146 __set_errno(status);
147 return result;
152 getspnam_r(const char *name, struct spwd *spwd, char *buffer,
153 size_t bufferSize, struct spwd **_result)
155 *_result = NULL;
157 KMessage message(BPrivate::B_REG_GET_USER);
158 message.AddString("name", name);
159 message.AddBool("shadow", true);
161 KMessage reply;
162 status_t error = BPrivate::send_authentication_request_to_registrar(message,
163 reply);
164 if (error != B_OK)
165 return error;
167 const char* password;
168 int32 lastChanged;
169 int32 min;
170 int32 max;
171 int32 warn;
172 int32 inactive;
173 int32 expiration;
174 int32 flags;
176 if ((error = reply.FindString("name", &name)) != B_OK
177 || (error = reply.FindString("shadow password", &password)) != B_OK
178 || (error = reply.FindInt32("last changed", &lastChanged)) != B_OK
179 || (error = reply.FindInt32("min", &min)) != B_OK
180 || (error = reply.FindInt32("max", &max)) != B_OK
181 || (error = reply.FindInt32("warn", &warn)) != B_OK
182 || (error = reply.FindInt32("inactive", &inactive)) != B_OK
183 || (error = reply.FindInt32("expiration", &expiration)) != B_OK
184 || (error = reply.FindInt32("flags", &flags)) != B_OK) {
185 return error;
188 error = BPrivate::copy_shadow_pwd_to_buffer(name, password, lastChanged,
189 min, max, warn, inactive, expiration, flags, spwd, buffer, bufferSize);
190 if (error == B_OK)
191 *_result = spwd;
193 return error;
197 struct spwd*
198 sgetspent(const char* line)
200 struct spwd* result = NULL;
201 int status = sgetspent_r(line, &sShadowPwdBuffer, sShadowPwdStringBuffer,
202 sizeof(sShadowPwdStringBuffer), &result);
203 if (status != 0)
204 __set_errno(status);
205 return result;
210 sgetspent_r(const char* _line, struct spwd *spwd, char *buffer,
211 size_t bufferSize, struct spwd** _result)
213 *_result = NULL;
215 if (_line == NULL)
216 return B_BAD_VALUE;
218 // we need a mutable copy of the line
219 char* line = strdup(_line);
220 if (line == NULL)
221 return B_NO_MEMORY;
222 MemoryDeleter _(line);
224 char* name;
225 char* password;
226 int lastChanged;
227 int min;
228 int max;
229 int warn;
230 int inactive;
231 int expiration;
232 int flags;
234 status_t status = BPrivate::parse_shadow_pwd_line(line, name, password,
235 lastChanged, min, max, warn, inactive, expiration, flags);
236 if (status != B_OK)
237 return status;
239 status = BPrivate::copy_shadow_pwd_to_buffer(name, password, lastChanged,
240 min, max, warn, inactive, expiration, flags, spwd, buffer, bufferSize);
241 if (status != B_OK)
242 return status;
244 *_result = spwd;
245 return 0;
249 struct spwd*
250 fgetspent(FILE* file)
252 struct spwd* result = NULL;
253 int status = fgetspent_r(file, &sShadowPwdBuffer, sShadowPwdStringBuffer,
254 sizeof(sShadowPwdStringBuffer), &result);
255 if (status != 0)
256 __set_errno(status);
257 return result;
262 fgetspent_r(FILE* file, struct spwd* spwd, char* buffer, size_t bufferSize,
263 struct spwd** _result)
265 *_result = NULL;
267 // read a line
268 char lineBuffer[LINE_MAX + 1];
269 __set_errno(0);
270 char* line = fgets(lineBuffer, sizeof(lineBuffer), file);
271 if (line == NULL) {
272 if (errno != 0)
273 return errno;
274 return ENOENT;
277 return sgetspent_r(line, spwd, buffer, bufferSize, _result);