1 // Copyright (c) 1999-2018 David Muse
2 // See the COPYING file for more information
3
4 #include <rudiments/userentry.h>
5 #include <rudiments/charstring.h>
6 #include <rudiments/bytestring.h>
7 #include <rudiments/sys.h>
8 #include <rudiments/error.h>
9 #include <rudiments/stdio.h>
10
11 #if defined(RUDIMENTS_HAVE_GETSPNAM) || defined(RUDIMENTS_HAVE_GETSPNAM_R)
12 #define RUDIMENTS_HAVE_SHADOW
13 #endif
14
15 #ifdef RUDIMENTS_HAVE_NETUSERGETINFO
16 #include <rudiments/dictionary.h>
17 #include <rudiments/groupentry.h>
18 #else
19 #include <pwd.h>
20 #endif
21
22 #ifdef RUDIMENTS_HAVE_SHADOW
23 // for spwd, functions
24 #include <shadow.h>
25 #endif
26
27 #ifdef RUDIMENTS_HAVE_WINDOWS_H
28 #include <windows.h>
29 #endif
30 #ifdef RUDIMENTS_HAVE_LM_H
31 #include <lm.h>
32 #endif
33 #ifdef RUDIMENTS_HAVE_SDDL_H
34 #include <sddl.h>
35 #endif
36
37 #ifdef RUDIMENTS_HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40
41 #define MAXBUFFER (32*1024)
42
43 class userentryprivate {
44 friend class userentry;
45 private:
46 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
47 passwd *_pwd;
48 #if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
49 defined(RUDIMENTS_HAVE_GETPWUID_R)
50 passwd _pwdbuffer;
51 char *_pwdcharbuffer;
52 #endif
53 char *_sidstr;
54 const char *_sid;
55 size_t _sidsize;
56 #ifdef RUDIMENTS_HAVE_SHADOW
57 spwd *_sp;
58 #if defined(RUDIMENTS_HAVE_GETSPNAM_R)
59 spwd _spbuffer;
60 char *_spcharbuffer;
61 #endif
62 #endif
63 #else
64 char *_name;
65 char *_password;
66 gid_t _primarygroupid;
67 char *_realname;
68 char *_homedir;
69 CHAR *_sidstr;
70 PSID _sid;
71 DWORD _sidsize;
72 uid_t _uid;
73 #endif
74 };
75
76 #if (!defined(RUDIMENTS_HAVE_GETPWNAM_R) || \
77 !defined(RUDIMENTS_HAVE_GETPWUID_R)) || \
78 defined(RUDIMENTS_HAVE_NETUSERGETINFO)
79 // LAME: not in the class
80 static threadmutex *uemutex;
81 #endif
82
83 #ifdef RUDIMENTS_HAVE_NETUSERGETINFO
84 // FIXME: move to charstring class
asciiToUnicode(const CHAR * in)85 static WCHAR *asciiToUnicode(const CHAR *in) {
86
87 int32_t size=MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,in,-1,NULL,0);
88 if (!size) {
89 return NULL;
90 }
91
92 WCHAR *out=new WCHAR[size];
93 if (!MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,in,-1,out,size)) {
94 delete[] out;
95 out=NULL;
96 }
97 return out;
98 }
99
100 // FIXME: move to charstring class
unicodeToAscii(const WCHAR * in)101 static CHAR *unicodeToAscii(const WCHAR *in) {
102
103 BOOL useddefaultchar;
104 int32_t size=WideCharToMultiByte(CP_ACP,0,in,-1,NULL,0,NULL,NULL);
105 if (!size) {
106 return NULL;
107 }
108
109 CHAR *out=new char[size];
110 if (!WideCharToMultiByte(CP_ACP,0,in,-1,out,size,
111 "?",&useddefaultchar)) {
112 delete[] out;
113 out=NULL;
114 }
115 return out;
116 }
117
118 static uid_t uid=0;
119 struct namesid {
120 char *name;
121 char *sidstr;
122 PSID sid;
123 DWORD sidsize;
124 };
125 static dictionary< uid_t, namesid * > uidmap;
126 // FIXME: clean up with init and exit methods like environment class
127
addUidMapping(const char * name,const char * sidstr,PSID sid,DWORD sidsize)128 static uid_t addUidMapping(const char *name,
129 const char *sidstr, PSID sid, DWORD sidsize) {
130
131 // check for existing mapping (by name only)
132 for (linkedlistnode< dictionarynode< uid_t, namesid * > *>
133 *node=uidmap.getList()->getFirst();
134 node; node=node->getNext()) {
135 namesid *ns=node->getValue()->getValue();
136 if (!charstring::compare(name,ns->name)) {
137 // reset the sid
138 delete[] ns->sidstr;
139 ns->sidstr=charstring::duplicate(sidstr);
140 delete[] (BYTE *)ns->sid;
141 ns->sid=bytestring::duplicate(sid,sidsize);
142 ns->sidsize=sidsize;
143 return node->getValue()->getKey();
144 }
145 }
146
147 // create a new entry
148 namesid *ns=new namesid;
149 ns->name=charstring::duplicate(name);
150 ns->sidstr=charstring::duplicate(sidstr);
151 ns->sid=bytestring::duplicate(sid,sidsize);
152 ns->sidsize=sidsize;
153
154 if (uemutex) {
155 uemutex->lock();
156 }
157 uid_t u=uid;
158 uid++;
159 if (uemutex) {
160 uemutex->unlock();
161 }
162
163 uidmap.setValue(u,ns);
164 return u;
165 }
166 #endif
167
168
userentry()169 userentry::userentry() {
170 pvt=new userentryprivate;
171 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
172 pvt->_pwd=NULL;
173 #if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
174 defined(RUDIMENTS_HAVE_GETPWUID_R)
175 bytestring::zero(&pvt->_pwdbuffer,sizeof(pvt->_pwdbuffer));
176 pvt->_pwdcharbuffer=NULL;
177 #endif
178 #ifdef RUDIMENTS_HAVE_SHADOW
179 pvt->_sp=NULL;
180 #ifdef RUDIMENTS_HAVE_GETSPNAM_R
181 bytestring::zero(&pvt->_spbuffer,
182 sizeof(pvt->_spbuffer));
183 pvt->_spcharbuffer=NULL;
184 #endif
185 #endif
186 #else
187 pvt->_name=NULL;
188 pvt->_password=NULL;
189 pvt->_primarygroupid=-1;
190 pvt->_realname=NULL;
191 pvt->_homedir=NULL;
192 pvt->_uid=(uid_t)-1;
193 #endif
194 pvt->_sidstr=NULL;
195 pvt->_sid=NULL;
196 pvt->_sidsize=0;
197 }
198
userentry(const userentry & p)199 userentry::userentry(const userentry &p) {
200 pvt=new userentryprivate;
201 initialize(p.getName());
202 }
203
operator =(const userentry & p)204 userentry &userentry::operator=(const userentry &p) {
205 if (this!=&p) {
206 initialize(p.getName());
207 }
208 return *this;
209 }
210
~userentry()211 userentry::~userentry() {
212 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
213 #if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
214 defined(RUDIMENTS_HAVE_GETPWUID_R)
215 delete[] pvt->_pwdcharbuffer;
216 #endif
217 #ifdef RUDIMENTS_HAVE_SHADOW
218 #ifdef RUDIMENTS_HAVE_GETSPNAM_R
219 delete[] pvt->_spcharbuffer;
220 #endif
221 #endif
222 delete[] pvt->_sidstr;
223 #else
224 delete[] pvt->_name;
225 delete[] pvt->_password;
226 delete[] pvt->_realname;
227 delete[] pvt->_homedir;
228 LocalFree(pvt->_sidstr);
229 delete[] (BYTE *)pvt->_sid;
230 #endif
231 delete pvt;
232 }
233
getName() const234 const char *userentry::getName() const {
235 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
236 return (pvt->_pwd)?pvt->_pwd->pw_name:NULL;
237 #else
238 return pvt->_name;
239 #endif
240 }
241
getPassword() const242 const char *userentry::getPassword() const {
243 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
244 #ifndef __VMS
245 return (pvt->_pwd)?pvt->_pwd->pw_passwd:NULL;
246 #else
247 return NULL;
248 #endif
249 #else
250 return pvt->_password;
251 #endif
252 }
253
getEncryptedPassword() const254 const char *userentry::getEncryptedPassword() const {
255 #ifdef RUDIMENTS_HAVE_SHADOW
256 return (pvt->_sp)?pvt->_sp->sp_pwdp:NULL;
257 #else
258 return NULL;
259 #endif
260 }
261
getLastChangeDate() const262 long userentry::getLastChangeDate() const {
263 #ifdef RUDIMENTS_HAVE_SHADOW
264 return (pvt->_sp)?pvt->_sp->sp_lstchg:-1;
265 #else
266 return -1;
267 #endif
268 }
269
getDaysBeforeChangeAllowed() const270 int32_t userentry::getDaysBeforeChangeAllowed() const {
271 #ifdef RUDIMENTS_HAVE_SHADOW
272 return (pvt->_sp)?pvt->_sp->sp_min:-1;
273 #else
274 return -1;
275 #endif
276 }
277
getDaysBeforeChangeRequired() const278 int32_t userentry::getDaysBeforeChangeRequired() const {
279 #ifdef RUDIMENTS_HAVE_SHADOW
280 return (pvt->_sp)?pvt->_sp->sp_max:-1;
281 #else
282 return -1;
283 #endif
284 }
285
getDaysBeforeExpirationWarning() const286 int32_t userentry::getDaysBeforeExpirationWarning() const {
287 #if defined(RUDIMENTS_HAVE_SHADOW) && defined(RUDIMENTS_HAVE_SP_WARN)
288 return (pvt->_sp)?pvt->_sp->sp_warn:-1;
289 #else
290 return -1;
291 #endif
292 }
293
getDaysOfInactivityAllowed() const294 int32_t userentry::getDaysOfInactivityAllowed() const {
295 #if defined(RUDIMENTS_HAVE_SHADOW) && defined(RUDIMENTS_HAVE_SP_INACT)
296 return (pvt->_sp)?pvt->_sp->sp_inact:-1;
297 #else
298 return -1;
299 #endif
300 }
301
getExpirationDate() const302 int32_t userentry::getExpirationDate() const {
303 #if defined(RUDIMENTS_HAVE_SHADOW) && defined(RUDIMENTS_HAVE_SP_EXPIRE)
304 return (pvt->_sp)?pvt->_sp->sp_expire:-1;
305 #else
306 return -1;
307 #endif
308 }
309
getFlag() const310 int32_t userentry::getFlag() const {
311 #if defined(RUDIMENTS_HAVE_SHADOW) && defined(RUDIMENTS_HAVE_SP_FLAG)
312 return (pvt->_sp)?(int32_t)pvt->_sp->sp_flag:-1;
313 #else
314 return -1;
315 #endif
316 }
317
getUserId() const318 uid_t userentry::getUserId() const {
319 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
320 return (pvt->_pwd)?pvt->_pwd->pw_uid:(uid_t)-1;
321 #else
322 return pvt->_uid;
323 #endif
324 }
325
getSidString() const326 const char *userentry::getSidString() const {
327 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
328 if (!pvt->_sidstr) {
329 if (pvt->_pwd) {
330 pvt->_sidstr=charstring::parseNumber(
331 (int64_t)pvt->_pwd->pw_uid);
332 }
333 pvt->_sid=pvt->_sidstr;
334 pvt->_sidsize=charstring::length(pvt->_sidstr);
335 }
336 return pvt->_sidstr;
337 #else
338 return pvt->_sidstr;
339 #endif
340 }
341
getSid() const342 const void *userentry::getSid() const {
343 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
344 if (!pvt->_sidstr) {
345 if (pvt->_pwd) {
346 pvt->_sidstr=charstring::parseNumber(
347 (int64_t)pvt->_pwd->pw_uid);
348 }
349 pvt->_sid=pvt->_sidstr;
350 pvt->_sidsize=charstring::length(pvt->_sidstr);
351 }
352 return pvt->_sid;
353 #else
354 return pvt->_sid;
355 #endif
356 }
357
getSidSize() const358 uint64_t userentry::getSidSize() const {
359 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
360 if (!pvt->_sidstr) {
361 if (pvt->_pwd) {
362 pvt->_sidstr=charstring::parseNumber(
363 (int64_t)pvt->_pwd->pw_uid);
364 }
365 pvt->_sid=pvt->_sidstr;
366 pvt->_sidsize=charstring::length(pvt->_sidstr);
367 }
368 return pvt->_sidsize;
369 #else
370 return pvt->_sidsize;
371 #endif
372 }
373
getPrimaryGroupId() const374 gid_t userentry::getPrimaryGroupId() const {
375 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
376 return (pvt->_pwd)?pvt->_pwd->pw_gid:(gid_t)-1;
377 #else
378 return (gid_t)pvt->_primarygroupid;
379 #endif
380 }
381
getRealName() const382 const char *userentry::getRealName() const {
383 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
384 #ifndef __VMS
385 return (pvt->_pwd)?pvt->_pwd->pw_gecos:NULL;
386 #else
387 return NULL;
388 #endif
389 #else
390 return pvt->_realname;
391 #endif
392 }
393
getHomeDirectory() const394 const char *userentry::getHomeDirectory() const {
395 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
396 return (pvt->_pwd)?pvt->_pwd->pw_dir:NULL;
397 #else
398 return pvt->_homedir;
399 #endif
400 }
401
getShell() const402 const char *userentry::getShell() const {
403 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
404 return (pvt->_pwd)?pvt->_pwd->pw_shell:NULL;
405 #else
406 // Under windows, users don't have default shells. As far as I know,
407 // the command line is always the same. You can run other shells
408 // but they're not tied to a user.
409 return NULL;
410 #endif
411 }
412
platformSupportsFormalSid()413 bool userentry::platformSupportsFormalSid() {
414 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
415 return false;
416 #else
417 return true;
418 #endif
419 }
420
needsMutex()421 bool userentry::needsMutex() {
422 #if (!defined(RUDIMENTS_HAVE_GETPWNAM_R) || \
423 !defined(RUDIMENTS_HAVE_GETPWUID_R)) || \
424 defined(RUDIMENTS_HAVE_NETUSERGETINFO)
425 return true;
426 #else
427 return false;
428 #endif
429 }
430
setMutex(threadmutex * mtx)431 void userentry::setMutex(threadmutex *mtx) {
432 #if (!defined(RUDIMENTS_HAVE_GETPWNAM_R) || \
433 !defined(RUDIMENTS_HAVE_GETPWUID_R)) || \
434 defined(RUDIMENTS_HAVE_NETUSERGETINFO)
435 uemutex=mtx;
436 #endif
437 }
438
initialize(const char * username)439 bool userentry::initialize(const char *username) {
440 return initialize(username,(uid_t)-1);
441 }
442
initialize(uid_t userid)443 bool userentry::initialize(uid_t userid) {
444 return initialize(NULL,userid);
445 }
446
initialize(const char * username,uid_t userid)447 bool userentry::initialize(const char *username, uid_t userid) {
448 #ifndef RUDIMENTS_HAVE_NETUSERGETINFO
449
450 // init return value
451 bool success=false;
452
453 // init buffers
454 delete[] pvt->_sidstr;
455 pvt->_sidstr=NULL;
456 pvt->_sid=NULL;
457 pvt->_sidsize=0;
458 #if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
459 defined(RUDIMENTS_HAVE_GETPWUID_R)
460 if (pvt->_pwd) {
461 pvt->_pwd=NULL;
462 delete[] pvt->_pwdcharbuffer;
463 pvt->_pwdcharbuffer=NULL;
464 }
465 #else
466 pvt->_pwd=NULL;
467 #endif
468 #if defined(RUDIMENTS_HAVE_GETSPNAM_R)
469 if (pvt->_sp) {
470 pvt->_sp=NULL;
471 delete[] pvt->_spcharbuffer;
472 pvt->_spcharbuffer=NULL;
473 }
474 #elif defined(RUDIMENTS_HAVE_GETSPNAM)
475 pvt->_sp=NULL;
476 #endif
477
478 // catch invalid name/id here...
479 // We have to do this rather than just letting one of the functions
480 // below fail because on some systems (SCO OSR) the actually interpret
481 // any negative user id as root and on others (SCO UnixWare) they
482 // interpret -1 as root. Ideally we'd check for any negative number,
483 // but on most systems, uid is unsigned. What a mess.
484 if (charstring::isNullOrEmpty(username) && userid==(uid_t)-1) {
485 return false;
486 }
487
488 // get password info
489 #if defined(RUDIMENTS_HAVE_GETPWNAM_R) && \
490 defined(RUDIMENTS_HAVE_GETPWUID_R)
491
492 // getpwnam_r and getpwuid_r are goofy.
493 // They will retrieve an arbitrarily large amount of data, but
494 // require that you pass them a pre-allocated buffer. If the
495 // buffer is too small, they returns an ENOMEM and you have to
496 // just make the buffer bigger and try again.
497 int64_t inc=sys::getSuggestedPasswordEntryBufferSize();
498 int64_t max=inc*32;
499 for (int64_t size=inc; size<max; size=size+inc) {
500
501 pvt->_pwdcharbuffer=new char[size];
502 #if defined(RUDIMENTS_HAVE_GETPWNAM_R_5) && \
503 defined(RUDIMENTS_HAVE_GETPWUID_R_5)
504 if (!((username)
505 ?(getpwnam_r(username,
506 &pvt->_pwdbuffer,
507 pvt->_pwdcharbuffer,size,
508 &pvt->_pwd))
509 :(getpwuid_r(userid,
510 &pvt->_pwdbuffer,
511 pvt->_pwdcharbuffer,size,
512 &pvt->_pwd)))) {
513 success=(pvt->_pwd!=NULL);
514 break;
515 }
516 #elif defined(RUDIMENTS_HAVE_GETPWNAM_R_4) && \
517 defined(RUDIMENTS_HAVE_GETPWUID_R_4)
518 if ((username)
519 ?(pvt->_pwd=getpwnam_r(username,
520 &pvt->_pwdbuffer,
521 pvt->_pwdcharbuffer,
522 size))
523 :(pvt->_pwd=getpwuid_r(userid,
524 &pvt->_pwdbuffer,
525 pvt->_pwdcharbuffer,
526 size))) {
527 success=true;
528 break;
529 }
530 #endif
531 delete[] pvt->_pwdcharbuffer;
532 pvt->_pwdcharbuffer=NULL;
533 pvt->_pwd=NULL;
534 if (error::getErrorNumber()!=ENOMEM) {
535 return false;
536 }
537 }
538 #else
539 success=(!(uemutex && !uemutex->lock()) &&
540 ((pvt->_pwd=((username)
541 ?getpwnam(username)
542 :getpwuid(userid)))!=NULL) &&
543 !(uemutex && !uemutex->unlock()));
544 #endif
545
546 if (!success) {
547 return false;
548 }
549
550 // get shadow info (but don't fail if this info isn't available)
551 #if defined(RUDIMENTS_HAVE_GETSPNAM_R)
552 // getspnam_r is goofy.
553 // It will retrieve an arbitrarily large amount of data, but
554 // requires that you pass it a pre-allocated buffer. If the
555 // buffer is too small, it returns an ENOMEM and you have to
556 // just make the buffer bigger and try again.
557 for (int32_t size=1024; size<MAXBUFFER; size=size+1024) {
558 pvt->_spcharbuffer=new char[size];
559 #if defined(RUDIMENTS_HAVE_GETSPNAM_R_5)
560 if (!getspnam_r(getName(),&pvt->_spbuffer,
561 pvt->_spcharbuffer,size,&pvt->_sp)) {
562 break;
563 }
564 #elif defined(RUDIMENTS_HAVE_GETSPNAM_R_4)
565 if ((pvt->_sp=getspnam_r(getName(),
566 &pvt->_spbuffer,
567 pvt->_spcharbuffer,size))) {
568 break;
569 }
570 #endif
571 delete[] pvt->_spcharbuffer;
572 pvt->_spcharbuffer=NULL;
573 pvt->_sp=NULL;
574 if (error::getErrorNumber()!=ENOMEM) {
575 break;
576 }
577 }
578 #elif defined(RUDIMENTS_HAVE_GETSPNAM)
579 if (!uemutex || uemutex->lock()) {
580 pvt->_sp=getspnam(const_cast<char *>(getName()));
581 }
582 if (uemutex) {
583 uemutex->unlock();
584 }
585 #endif
586
587 return success;
588
589 #else
590
591 delete[] pvt->_name;
592 pvt->_name=NULL;
593 pvt->_primarygroupid=-1;
594 delete[] pvt->_realname;
595 pvt->_realname=NULL;
596 delete[] pvt->_password;
597 pvt->_password=NULL;
598 delete[] pvt->_homedir;
599 pvt->_homedir=NULL;
600 LocalFree(pvt->_sidstr);
601 pvt->_sidstr=NULL;
602 delete[] (BYTE *)pvt->_sid;
603 pvt->_sid=NULL;
604 pvt->_sidsize=0;
605 pvt->_uid=(uid_t)-1;
606
607 if (username) {
608
609 // get the user's SID
610 DWORD dnsize=0;
611 SID_NAME_USE peuse;
612 LookupAccountName(NULL,username,
613 NULL,&pvt->_sidsize,
614 NULL,&dnsize,&peuse);
615 pvt->_sid=(PSID)new BYTE[pvt->_sidsize];
616 bytestring::zero(pvt->_sid,pvt->_sidsize);
617 CHAR *dn=new CHAR[dnsize];
618 bytestring::zero(dn,dnsize);
619 bool failed=(LookupAccountName(NULL,username,
620 pvt->_sid,&pvt->_sidsize,
621 dn,&dnsize,&peuse)==FALSE ||
622 IsValidSid(pvt->_sid)==FALSE
623 #if _WIN32_WINNT>=0x0500
624 || ConvertSidToStringSid(pvt->_sid,
625 &pvt->_sidstr)==FALSE
626 #endif
627 );
628 delete[] dn;
629 if (failed) {
630 return false;
631 }
632
633 // convert username to unicode...
634 WCHAR *usernamew=asciiToUnicode(username);
635 if (!usernamew) {
636 return false;
637 }
638
639 // get user info
640 USER_INFO_2 *buffer=NULL;
641 if (NetUserGetInfo(NULL,usernamew,2,(BYTE **)&buffer)!=
642 NERR_Success) {
643 delete[] usernamew;
644 return false;
645 }
646 delete[] usernamew;
647
648 // convert the unicode values to ascii
649 pvt->_name=unicodeToAscii(buffer->usri2_name);
650 pvt->_password=unicodeToAscii(buffer->usri2_password);
651 pvt->_realname=unicodeToAscii(buffer->usri2_full_name);
652 pvt->_homedir=unicodeToAscii(buffer->usri2_home_dir);
653 NetApiBufferFree(buffer);
654
655 // get primary group
656 // FIXME:
657 // On non-servers, there are no local groups and the primary
658 // group is None. On servers (>Win2K) NetUserGetInfo can be
659 // used with a level of 3 and get the primary group RID in the
660 // resulting USER_INFO_3 struct. It should then somehow be
661 // possible to convert that into a group name. How do I tell
662 // if I'm on a server? What should be done for <=Win2K?
663 pvt->_primarygroupid=groupentry::getGroupId("None");
664
665 // add mapping
666 pvt->_uid=addUidMapping(pvt->_name,pvt->_sidstr,
667 pvt->_sid,pvt->_sidsize);
668
669 } else {
670
671 // look up the uid in the map
672 namesid *ns;
673 if (uidmap.getValue(userid,&ns)) {
674 return initialize(ns->name);
675 }
676 return false;
677 }
678 return true;
679 #endif
680 }
681
getName(uid_t userid)682 char *userentry::getName(uid_t userid) {
683 userentry pwd;
684 return (pwd.initialize(userid))?
685 charstring::duplicate(pwd.getName()):NULL;
686 }
687
getUserId(const char * username)688 uid_t userentry::getUserId(const char *username) {
689 userentry pwd;
690 return (pwd.initialize(username))?pwd.getUserId():(uid_t)-1;
691 }
692
getSidString(const char * username)693 char *userentry::getSidString(const char *username) {
694 userentry pwd;
695 return (pwd.initialize(username))?
696 charstring::duplicate(pwd.getSidString()):NULL;
697 }
698