1 #include "uniconfroot.h"
4 #include "wvtclstring.h"
13 #include <sys/types.h>
17 #define MY_RETURN(x) do \
19 pthread_mutex_unlock(&nssunilock); \
24 pthread_mutex_lock(&nssunilock); \
27 #define LOCK pthread_mutex_lock(&nssunilock)
28 #define UNLOCK pthread_mutex_unlock(&nssunilock)
30 pthread_mutex_t nssunilock
= PTHREAD_MUTEX_INITIALIZER
;
33 #define LOG(info...) log(info)
34 static WvLog
log("nss-uniconf", WvLog::Debug4
);
35 static WvLogFile
logger("/tmp/nss-uniconf", WvLog::Debug5
);
37 #define LOG(info...) ;
38 static WvLogFileBase
logger("/dev/null", WvLog::Debug5
);
41 static UniConfRoot
*cfgroot
= NULL
;
42 static UniConf cfg
, fnames
, uids
, groups
;
43 static UniConf::Iter
*uiter
= NULL
;
44 static UniConf::Iter
*giter
= NULL
;
45 static UniConf::Iter
*siter
= NULL
;
49 // FIXME: when do we plan to _free_ these?
52 // connect to the local UniConf daemon
53 cfgroot
= new UniConfRoot();
54 cfg
= UniConf(*cfgroot
);
56 // cache in the daemon, not here
57 cfg
.mount("auto:ca/nit/nssuniconf");
59 fnames
= cfg
["Full Names"];
61 groups
= cfg
["Groups"];
63 uiter
= new UniConf::Iter(uids
);
64 giter
= new UniConf::Iter(uids
);
65 siter
= new UniConf::Iter(uids
);
73 gid_t newgrp
, gid_t
**groupsp
,
74 long int *start
, long int *size
, long int limit
)
76 if (*start
== *size
&& limit
<= 0)
78 LOG("Not enough room for group entries. Reallocating.\n");
80 (gid_t
*)realloc((*groupsp
), (2 * (*size
) + 1) * sizeof(gid_t
));
84 LOG("Failed to reallocate.\n");
89 *size
= 2 * (*size
) + 1;
94 (*groupsp
)[*start
] = newgrp
;
98 LOG("Successfully added group %s to the list", newgrp
);
102 static char *putmatch(WvBuf
&out
, WvStringParm s
)
104 WvConstStringBuffer
buf(s
);
106 int startofs
= out
.used();
109 out
.putstr(wvtcl_getword(buf
));
115 return (char *)out
.mutablepeek(startofs
, out
.used() - (unsigned)startofs
);
118 static char **putmatches(WvBuf
&out
, WvStringParm s
)
123 if (0 == users
.count())
126 int startofl
= out
.used();
127 int currptr
= startofl
;
129 // an extra ptr for NULL at the end
130 size_t ptrsize
= (users
.count() + 1)*sizeof(char *);
131 char *ptrs
= new char[ptrsize
];
133 memset(ptrs
, 0, ptrsize
);
134 out
.put(ptrs
, ptrsize
);
138 // dump the strings into the buffer
139 WvStringList::Iter
i(users
);
140 for (i
.rewind(); i
.next(); )
142 char *bufstr
= putmatch(out
, i());
143 out
.poke(&bufstr
, currptr
, sizeof(char *));
144 currptr
+= sizeof(char *);
147 return (char **)out
.mutablepeek(startofl
, out
.used() - (unsigned)startofl
);
151 static enum nss_status
pwmatch(struct passwd
*pw
, int *errnop
,
152 char *buf
, size_t buflen
,
153 WvStringParm username
)
155 WvInPlaceBuf
out(buf
, 0, buflen
);
157 WvString
homedir("/export/home/%s", username
);
158 WvString
shell("/bin/bash");
159 WvString
gecos(fnames
[username
].getme());
163 pw
->pw_name
= putmatch(out
, username
);
164 pw
->pw_passwd
= putmatch(out
, "x");
165 pw
->pw_uid
= uids
[username
].getmeint(65534);
166 pw
->pw_gid
= uids
[username
].getmeint(65534);
167 pw
->pw_gecos
= putmatch(out
, gecos
);
168 pw
->pw_dir
= putmatch(out
, homedir
);
169 pw
->pw_shell
= putmatch(out
, shell
);
173 *errnop
= errno
= ERANGE
;
174 return NSS_STATUS_TRYAGAIN
;
179 return NSS_STATUS_SUCCESS
;
184 static enum nss_status
grmatch(struct group
*gr
, int *errnop
,
185 char *buf
, size_t buflen
,
186 WvStringParm username
)
188 WvInPlaceBuf
out(buf
, 0, buflen
);
189 WvString members
= groups
[username
].getme();
193 gr
->gr_name
= putmatch(out
, username
);
194 gr
->gr_passwd
= putmatch(out
, "x");
195 gr
->gr_gid
= uids
[username
].getmeint(65534);
196 gr
->gr_mem
= putmatches(out
, members
);
200 *errnop
= errno
= ERANGE
;
201 return NSS_STATUS_TRYAGAIN
;
206 return NSS_STATUS_SUCCESS
;
211 static enum nss_status
spmatch(struct spwd
*sp
, int *errnop
,
212 char *buf
, size_t buflen
,
213 WvStringParm username
)
215 WvInPlaceBuf
out(buf
, 0, buflen
);
216 time_t now
= time(NULL
);
217 long lastchg
= (now
/ (60*60*24)) - 1;
219 sp
->sp_namp
= putmatch(out
, username
);
221 sp
->sp_lstchg
= lastchg
;
223 sp
->sp_max
= LONG_MAX
;
225 sp
->sp_inact
= LONG_MAX
;
226 sp
->sp_expire
= LONG_MAX
;
230 *errnop
= errno
= ERANGE
;
231 return NSS_STATUS_TRYAGAIN
;
236 return NSS_STATUS_SUCCESS
;
241 extern "C" enum nss_status
_nss_uniconf_getpwnam_r(
242 const char *user
, struct passwd
*pw
,
243 char *buf
, size_t buflen
, int *errnop
)
246 LOG("%s(%s) called.\n", __func__
, user
);
248 enum nss_status ret
= NSS_STATUS_NOTFOUND
;
249 *errnop
= errno
= ENOENT
;
251 if (uids
[user
].exists())
252 ret
= pwmatch(pw
, errnop
, buf
, buflen
, user
);
258 extern "C" enum nss_status
_nss_uniconf_getpwuid_r(
259 uid_t uid
, struct passwd
*pw
,
260 char *buf
, size_t buflen
, int *errnop
)
263 LOG("%s(%s) called.\n", __func__
, uid
);
266 enum nss_status ret
= NSS_STATUS_NOTFOUND
;
267 *errnop
= errno
= ENOENT
;
269 UniConf::Iter
i(uids
);
270 for (i
.rewind(); i
.next(); )
272 if (uid
== (unsigned)i
._value().num())
274 username
= i().key().printable();
275 ret
= pwmatch(pw
, errnop
, buf
, buflen
, username
);
285 extern "C" enum nss_status
_nss_uniconf_getgrnam_r(
286 const char *user
, struct group
*gr
,
287 char *buf
, size_t buflen
, int *errnop
)
290 LOG("%s(%s) called.\n", __func__
, user
);
292 enum nss_status ret
= NSS_STATUS_NOTFOUND
;
293 *errnop
= errno
= ENOENT
;
295 if (uids
[user
].exists())
296 ret
= grmatch(gr
, errnop
, buf
, buflen
, user
);
302 extern "C" enum nss_status
_nss_uniconf_getgrgid_r(
303 gid_t gid
, struct group
*gr
,
304 char *buf
, size_t buflen
, int *errnop
)
307 LOG("%s(%s) called.\n", __func__
, gid
);
310 enum nss_status ret
= NSS_STATUS_NOTFOUND
;
311 *errnop
= errno
= ENOENT
;
313 UniConf::Iter
i(uids
);
314 for (i
.rewind(); i
.next(); )
316 if (gid
== (unsigned)i
._value().num())
318 username
= i().key().printable();
319 ret
= grmatch(gr
, errnop
, buf
, buflen
, username
);
327 extern "C" enum nss_status
_nss_uniconf_getspnam_r(
328 const char *user
, struct spwd
*sp
,
329 char *buf
, size_t buflen
, int *errnop
)
332 LOG("%s(%s) called.\n", __func__
, user
);
334 enum nss_status ret
= NSS_STATUS_NOTFOUND
;
335 *errnop
= errno
= ENOENT
;
337 if (uids
[user
].exists())
338 ret
= spmatch(sp
, errnop
, buf
, buflen
, user
);
344 extern "C" enum nss_status
_nss_uniconf_getspuid_r(
345 uid_t uid
, struct spwd
*sp
,
346 char *buf
, size_t buflen
, int *errnop
)
349 LOG("%s(%s) called.\n", __func__
, uid
);
352 enum nss_status ret
= NSS_STATUS_NOTFOUND
;
353 *errnop
= errno
= ENOENT
;
355 UniConf::Iter
i(uids
);
356 for (i
.rewind(); i
.next(); )
358 if (uid
== (unsigned)i
._value().num())
360 username
= i().key().printable();
361 ret
= spmatch(sp
, errnop
, buf
, buflen
, username
);
369 extern "C" enum nss_status
_nss_uniconf_setpwent()
372 LOG("%s() called.\n", __func__
);
374 MY_RETURN(NSS_STATUS_SUCCESS
);
377 extern "C" enum nss_status
_nss_uniconf_setgrent()
380 LOG("%s() called.\n", __func__
);
382 MY_RETURN(NSS_STATUS_SUCCESS
);
385 extern "C" enum nss_status
_nss_uniconf_endpwent()
388 LOG("%s() called.\n", __func__
);
390 MY_RETURN(NSS_STATUS_SUCCESS
);
393 extern "C" enum nss_status
_nss_uniconf_endgrent()
396 LOG("%s() called.\n", __func__
);
398 MY_RETURN(NSS_STATUS_SUCCESS
);
401 extern "C" enum nss_status
_nss_uniconf_setspent()
404 LOG("%s() called.\n", __func__
);
406 MY_RETURN(NSS_STATUS_SUCCESS
);
409 extern "C" enum nss_status
_nss_uniconf_endspent()
412 LOG("%s() called.\n", __func__
);
414 MY_RETURN(NSS_STATUS_SUCCESS
);
417 extern "C" enum nss_status
_nss_uniconf_getpwent_r(
418 struct passwd
*pw
, char *buf
,
419 int buflen
, int *errnop
)
422 LOG("%s() called.\n", __func__
);
424 UniConf::Iter
&i
= *uiter
;
428 WvString username
= i().key().printable();
429 MY_RETURN(_nss_uniconf_getpwnam_r(username
, pw
,
430 buf
, buflen
, errnop
));
435 errno
= *errnop
= ENOENT
;
436 MY_RETURN(NSS_STATUS_NOTFOUND
);
439 extern "C" enum nss_status
_nss_uniconf_getgrent_r(
440 struct group
*gr
, char *buf
,
441 int buflen
, int *errnop
)
444 LOG("%s() called.\n", __func__
);
446 UniConf::Iter
&i
= *uiter
;
450 WvString username
= i().key().printable();
451 MY_RETURN(_nss_uniconf_getgrnam_r(username
, gr
,
452 buf
, buflen
, errnop
));
457 errno
= *errnop
= ENOENT
;
458 MY_RETURN(NSS_STATUS_NOTFOUND
);
461 extern "C" enum nss_status
_nss_uniconf_getspent_r(
462 struct spwd
*sp
, char *buf
,
463 int buflen
, int *errnop
)
466 LOG("%s() called.\n", __func__
);
468 UniConf::Iter
&i
= *uiter
;
472 WvString username
= i().key().printable();
473 MY_RETURN(_nss_uniconf_getspnam_r(username
, sp
,
474 buf
, buflen
, errnop
));
479 errno
= *errnop
= ENOENT
;
480 MY_RETURN(NSS_STATUS_NOTFOUND
);
483 extern "C" struct passwd
*_nss_uniconf_getpwent(void)
486 LOG("%s() called.\n", __func__
);
488 struct passwd
*ret
= (struct passwd
*)malloc(sizeof(struct passwd
));
493 size_t bufsize
= sysconf(_SC_GETPW_R_SIZE_MAX
);
494 UniConf::Iter
&i
= *uiter
;
498 char *buf
= (char *)malloc(bufsize
);
502 WvString username
= i().key().printable();
506 enum nss_status status
=
507 _nss_uniconf_getpwnam_r(username
, ret
,
508 buf
, bufsize
, &errnum
);
511 if (NSS_STATUS_SUCCESS
== status
)
525 extern "C" struct group
*_nss_uniconf_getgrent(void)
528 LOG("%s() called.\n", __func__
);
530 struct group
*ret
= (struct group
*)malloc(sizeof(struct group
));
535 size_t bufsize
= sysconf(_SC_GETGR_R_SIZE_MAX
);
536 UniConf::Iter
&i
= *giter
;
540 char *buf
= (char *)malloc(bufsize
);
544 WvString username
= i().key().printable();
548 enum nss_status status
=
549 _nss_uniconf_getgrnam_r(username
, ret
,
550 buf
, bufsize
, &errnum
);
553 if (NSS_STATUS_SUCCESS
== status
)
567 extern "C" struct spwd
*_nss_uniconf_getspent(void)
570 LOG("%s() called.\n", __func__
);
572 struct spwd
*ret
= (struct spwd
*)malloc(sizeof(struct spwd
));
577 size_t bufsize
= UT_NAMESIZE
;
578 UniConf::Iter
&i
= *siter
;
582 char *buf
= (char *)malloc(bufsize
);
586 WvString username
= i().key().printable();
590 enum nss_status status
=
591 _nss_uniconf_getspnam_r(username
, ret
,
592 buf
, bufsize
, &errnum
);
595 if (NSS_STATUS_SUCCESS
== status
)
609 extern "C" enum nss_status
_nss_uniconf_initgroups_dyn(
610 const char *user
, gid_t group
, long int *start
, long int *size
,
611 gid_t
**groupsp
, long int limit
, int *errnop
)
614 LOG("%s() called.\n", __func__
);
616 if (!user
|| !uids
[user
].exists())
618 errno
= *errnop
= ENOENT
;
619 MY_RETURN(NSS_STATUS_NOTFOUND
);
624 errno
= *errnop
= EINVAL
;
625 MY_RETURN(NSS_STATUS_UNAVAIL
);
633 UniConf::Iter
i(groups
);
634 for (i
.rewind(); i
.next(); )
636 members
= i().getme();
637 mlist
.split(members
, " ");
638 curr
= uids
[i().key().printable()].getmeint();
639 nmem
= mlist
.count();
641 if (curr
== group
|| !nmem
)
646 if (mlist
.popstr() == user
)
648 LOG("I think %s is in group %s.\n", user
, curr
);
649 if (!putgroup(curr
, groupsp
, start
, size
, limit
))
651 errno
= *errnop
= ENOMEM
;
652 MY_RETURN(NSS_STATUS_TRYAGAIN
);
663 MY_RETURN(NSS_STATUS_SUCCESS
);