/* -*-c-*-
*
- * $Id: userdb.c,v 1.3 1997/08/07 09:44:29 mdw Exp $
+ * $Id: userdb.c,v 1.10 2003/10/12 00:39:16 mdw Exp $
*
* User database management
*
- * (c) 1997 EBI
+ * (c) 1998 EBI
*/
/*----- Licensing notice --------------------------------------------------*
/*----- Revision history --------------------------------------------------*
*
* $Log: userdb.c,v $
+ * Revision 1.10 2003/10/12 00:39:16 mdw
+ * Light fixes for strange building.
+ *
+ * Revision 1.9 2003/10/12 00:14:55 mdw
+ * Major overhaul. Now uses DSA signatures rather than the bogus symmetric
+ * encrypt-and-hope thing. Integrated with mLib and Catacomb.
+ *
+ * Revision 1.8 1998/06/08 11:21:22 mdw
+ * Fixed bug in password and group file reading: strtok doesn't handle
+ * double colons nicely.
+ *
+ * Revision 1.7 1998/04/23 13:27:46 mdw
+ * Switch to using the ypstuff interface to YP server.
+ *
+ * Revision 1.6 1998/01/12 16:46:33 mdw
+ * Fix copyright date.
+ *
+ * Revision 1.5 1997/09/17 10:24:08 mdw
+ * Use `uid_t' instead of `int' for uids and gids. Not quite sure why I
+ * didn't do this before.
+ *
+ * Revision 1.4 1997/08/20 16:24:58 mdw
+ * Patch memory leak. Rename `userdb_reinit' to `userdb_end' for more
+ * sensible restart.
+ *
* Revision 1.3 1997/08/07 09:44:29 mdw
* Read NIS-based passwords from the YP server directly, rather than using
* `popen(ypcat)', which is probably both slower and less secure.
#include <sys/types.h>
-#ifdef HAVE_YP
-# include <rpc/rpc.h>
-# include <rpcsvc/ypclnt.h>
-# include <rpcsvc/yp_prot.h>
-#endif
-
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
+/* --- mLib headers --- */
+
+#include <mLib/alloc.h>
+#include <mLib/sym.h>
+#include <mLib/trace.h>
+
/* --- Local headers --- */
#include "become.h"
-#include "sym.h"
#include "userdb.h"
-#include "utils.h"
+#include "ypstuff.h"
/*----- Type definitions --------------------------------------------------*/
static void userdb__createMap(userdb__map *m)
{
- sym_createTable(&m->nmap);
- sym_createTable(&m->idmap);
+ sym_create(&m->nmap);
+ sym_create(&m->idmap);
m->list = 0;
}
*
* Arguments: @userdb__map *m@ = pointer to the map block
* @const char *name@ = pointer to the item's name
- * @int id@ = the item's id number
+ * @uid_t id@ = the item's id number
* @void *rec@ = pointer to the actual record
*
* Returns: ---
static void userdb__addToMap(userdb__map *m,
const char *name,
- int id, void *rec)
+ uid_t id, void *rec)
{
unsigned f;
userdb__sym *s;
/* --- @userdb__byId@ --- *
*
* Arguments: @userdb__map *m@ = pointer to a map block
- * @int id@ = id number to find
+ * @uid_t id@ = id number to find
*
* Returns: A pointer to the appropriate block, or zero if not found.
*
* Use: Looks up an ID in a mapping, and returns the result.
*/
-static void *userdb__byId(userdb__map *m, int id)
+static void *userdb__byId(userdb__map *m, uid_t id)
{
userdb__sym *s = sym_find(&m->idmap, (char *)&id, sizeof(id), 0, 0);
return (s ? s->rec : 0);
{
userdb__node *n, *t;
- sym_destroyTable(&m->nmap);
- sym_destroyTable(&m->idmap);
+ sym_destroy(&m->nmap);
+ sym_destroy(&m->idmap);
for (n = m->list; n; n = t) {
t = n->next;
* Use: Writes a user's informationt to a stream.
*/
-#ifdef TRACING
+#ifndef NTRACE
static void userdb__dumpUser(const struct passwd *pw)
{
#endif
+/* --- @userdb__split@ --- *
+ *
+ * Arguments: @char *p@ = pointer to string
+ * @char **v@ = pointer to vector to fill in
+ * @int sz@ = maximum number of fields to split
+ *
+ * Returns: Number of fields extracted.
+ *
+ * Use: Splits a string into fields at colon characters.
+ */
+
+static int userdb__split(char *p, char **v, int sz)
+{
+ int count = 0;
+
+ *v++ = p; sz--; count++;
+ if (!sz)
+ goto done;
+ while (*p) {
+ if (*p++ == ':') {
+ p[-1] = 0;
+ *v++ = p; sz--; count++;
+ if (!sz)
+ goto done;
+ }
+ }
+ while (sz--)
+ *v++ = 0;
+
+done:
+ return (count);
+}
+
/* --- @userdb_copyUser@ --- *
*
* Arguments: @struct passwd *pw@ = pointer to block to copy
static struct passwd *userdb__buildUser(char *s)
{
struct passwd *pw = xmalloc(sizeof(*pw));
+ char *v[7];
- s = strtok(s, ":"); if (!s) goto tidy_0; pw->pw_name = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_1; pw->pw_passwd = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; pw->pw_uid = atoi(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; pw->pw_gid = atoi(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; pw->pw_gecos = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_3; pw->pw_dir = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_4; pw->pw_shell = xstrdup(s);
- return (pw);
-
- /* --- Error handling --- */
-
-tidy_4:
- free(pw->pw_dir);
-tidy_3:
- free(pw->pw_gecos);
-tidy_2:
- free(pw->pw_passwd);
-tidy_1:
- free(pw->pw_name);
-tidy_0:
- free(pw);
+ if (userdb__split(s, v, 7) < 7) {
+ free(pw);
+ return (0);
+ }
- return (0);
+ pw->pw_name = xstrdup(v[0]);
+ pw->pw_passwd = xstrdup(v[1]);
+ pw->pw_uid = (uid_t)atol(v[2]);
+ pw->pw_gid = (gid_t)atol(v[3]);
+ pw->pw_gecos = xstrdup(v[4]);
+ pw->pw_dir = xstrdup(v[5]);
+ pw->pw_shell = xstrdup(v[6]);
+ return (pw);
}
/* --- @userdb_freeUser@ --- *
* Use: Writes a group's information to a stream.
*/
-#ifdef TRACING
+#ifndef NTRACE
static void userdb__dumpGroup(const struct group *gr)
{
static struct group *userdb__buildGroup(char *s)
{
struct group *gr = xmalloc(sizeof(*gr));
- char *p;
+ char *v[4];
int i;
/* --- Do the easy bits --- */
- s = strtok(s, ":"); if (!s) goto tidy_0; gr->gr_name = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_1; gr->gr_passwd = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; gr->gr_gid = atoi(s);
-
- /* --- Find the start of the member list --- */
-
- s = strtok(0, "");
- if (!s)
- goto tidy_2;
+ if (userdb__split(s, v, 4) < 3) {
+ free(gr);
+ return (0);
+ }
+ gr->gr_name = xstrdup(v[0]);
+ gr->gr_passwd = xstrdup(v[1]);
+ gr->gr_gid = (gid_t)atol(v[2]);
/* --- Count the number of members --- */
- p = s;
+ s = v[3];
i = 0;
- for (;;) {
- i++;
- if ((p = strpbrk(p, ",")) == 0)
- break;
- p++;
+ if (s && s[0]) {
+ for (;;) {
+ i++;
+ if ((s = strpbrk(s, ",")) == 0)
+ break;
+ s++;
+ }
}
/* --- Allocate the block and fill it --- */
gr->gr_mem = xmalloc((i + 1) * sizeof(char *));
i = 0;
- s = strtok(s, ",");
- do {
- gr->gr_mem[i++] = xstrdup(s);
- s = strtok(0, ",");
- } while (s);
+ if (v[3]) {
+ s = strtok(v[3], ",");
+ while (s) {
+ gr->gr_mem[i++] = xstrdup(s);
+ s = strtok(0, ",");
+ }
+ }
gr->gr_mem[i] = 0;
return (gr);
-
- /* --- Various tidying-up things --- */
-
-tidy_2:
- free(gr->gr_passwd);
-tidy_1:
- free(gr->gr_name);
-tidy_0:
- free(gr);
-
- return (0);
}
/* --- @userdb_freeGroup@ --- *
{ userdb_iterateUsers_r(&userdb__useri); }
void userdb_iterateUsers_r(userdb_iter *i)
-{ sym_createIter(i, &userdb__users.nmap); }
+{ sym_mkiter(i, &userdb__users.nmap); }
/* --- @userdb_nextUser@, @userdb_nextUser_r@ --- *
*
{ userdb_iterateGroups_r(&userdb__groupi); }
void userdb_iterateGroups_r(userdb_iter *i)
-{ sym_createIter(i, &userdb__groups.nmap); }
+{ sym_mkiter(i, &userdb__groups.nmap); }
/* --- @userdb_nextGroup@, @userdb_nextGroup_r@ --- *
*
if (pw && !userdb__byName(&userdb__users, pw->pw_name)) {
IF_TRACING(TRACE_DEBUG, userdb__dumpUser(pw); )
userdb__addToMap(&userdb__users, pw->pw_name, pw->pw_uid, pw);
- }
+ } else
+ userdb_freeUser(pw);
free(cv);
return (0);
}
if (gr && !userdb__byName(&userdb__groups, gr->gr_name)) {
IF_TRACING(TRACE_DEBUG, userdb__dumpGroup(gr); )
userdb__addToMap(&userdb__groups, gr->gr_name, gr->gr_gid, gr);
- }
+ } else
+ userdb_freeGroup(gr);
free(cv);
return (0);
}
void userdb_yp(void)
{
- char *ypdom;
-
/* --- Bind to a server --- */
- if (yp_get_default_domain(&ypdom) ||
- yp_bind(ypdom))
+ ypstuff_bind();
+ if (!yp_domain)
return;
T( trace(TRACE_DEBUG, "debug: adding NIS users"); )
{
static struct ypall_callback ucb = { userdb__foreachUser, 0 };
- yp_all(ypdom, "passwd.byuid", &ucb);
+ yp_all(yp_domain, "passwd.byuid", &ucb);
}
/* --- Fetch the groups map --- */
{
static struct ypall_callback gcb = { userdb__foreachGroup, 0 };
- yp_all(ypdom, "group.bygid", &gcb);
+ yp_all(yp_domain, "group.bygid", &gcb);
}
-
- yp_unbind(ypdom);
}
#else
userdb__createMap(&userdb__groups);
}
-/* --- @userdb_reinit@ --- *
+/* --- @userdb_end@ --- *
*
* Arguments: ---
*
* Returns: ---
*
- * Use: Reinitialises the user database.
+ * Use: Closes down the user database.
*/
-void userdb_reinit(void)
+void userdb_end(void)
{
userdb__clearMap(&userdb__users, userdb_freeUser);
userdb__clearMap(&userdb__groups, userdb_freeGroup);
- userdb_init();
}
/*----- Test rig ----------------------------------------------------------*/
int main(void)
{
ego("userdb-test");
- traceon(stderr, TRACE_ALL);
+ trace_on(stdout, TRACE_ALL);
userdb_init();
- dumpit("cleared");
- userdb_yp();
- dumpit("yp");
userdb_local();
- dumpit("local");
+ userdb_yp();
+ dumpit("spong");
+/* printf("loaded (%lu)\n", track_memused()); */
+ getchar();
+ for (;;) {
+ userdb_end();
+/* printf("cleared (%lu)\n", track_memused()); */
+/* track_memlist(); */
+ userdb_init();
+ userdb_local();
+ userdb_yp();
+/* printf("reloaded (%lu)\n", track_memused()); */
+ getchar();
+ }
return (0);
}