Home | History | Annotate | Line # | Download | only in irs
nis_pw.c revision 1.1.1.1.2.2
      1 /*	$NetBSD: nis_pw.c,v 1.1.1.1.2.2 2009/05/13 18:52:12 jym Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
      5  * Copyright (c) 1996,1999 by Internet Software Consortium.
      6  *
      7  * Permission to use, copy, modify, and distribute this software for any
      8  * purpose with or without fee is hereby granted, provided that the above
      9  * copyright notice and this permission notice appear in all copies.
     10  *
     11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  */
     19 
     20 #if defined(LIBC_SCCS) && !defined(lint)
     21 static const char rcsid[] = "Id: nis_pw.c,v 1.4 2005/04/27 04:56:33 sra Exp";
     22 #endif /* LIBC_SCCS and not lint */
     23 
     24 /* Imports */
     25 
     26 #include "port_before.h"
     27 
     28 #if !defined(WANT_IRS_PW) || !defined(WANT_IRS_NIS)
     29 static int __bind_irs_pw_unneeded;
     30 #else
     31 
     32 #include <sys/param.h>
     33 #include <sys/types.h>
     34 #include <netinet/in.h>
     35 #include <arpa/nameser.h>
     36 #include <resolv.h>
     37 #include <isc/memcluster.h>
     38 #include <rpc/rpc.h>
     39 #include <rpc/xdr.h>
     40 #include <rpcsvc/yp_prot.h>
     41 #include <rpcsvc/ypclnt.h>
     42 
     43 #include <errno.h>
     44 #include <fcntl.h>
     45 #include <pwd.h>
     46 #include <stdio.h>
     47 #include <stdlib.h>
     48 #include <string.h>
     49 #include <unistd.h>
     50 
     51 #include <isc/memcluster.h>
     52 
     53 #include <irs.h>
     54 
     55 #include "port_after.h"
     56 
     57 #include "irs_p.h"
     58 #include "nis_p.h"
     59 
     60 /* Definitions */
     61 
     62 struct pvt {
     63 	int		needrewind;
     64 	char *		nis_domain;
     65 	char *		curkey_data;
     66 	int		curkey_len;
     67 	char *		curval_data;
     68 	int		curval_len;
     69 	struct passwd 	passwd;
     70 	char *		pwbuf;
     71 };
     72 
     73 enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
     74 
     75 static /*const*/ char passwd_byname[] =	"passwd.byname";
     76 static /*const*/ char passwd_byuid[] =	"passwd.byuid";
     77 
     78 /* Forward */
     79 
     80 static void			pw_close(struct irs_pw *);
     81 static struct passwd *		pw_next(struct irs_pw *);
     82 static struct passwd *		pw_byname(struct irs_pw *, const char *);
     83 static struct passwd *		pw_byuid(struct irs_pw *, uid_t);
     84 static void			pw_rewind(struct irs_pw *);
     85 static void			pw_minimize(struct irs_pw *);
     86 
     87 static struct passwd *		makepasswdent(struct irs_pw *);
     88 static void			nisfree(struct pvt *, enum do_what);
     89 
     90 /* Public */
     91 
     92 struct irs_pw *
     93 irs_nis_pw(struct irs_acc *this) {
     94 	struct irs_pw *pw;
     95 	struct pvt *pvt;
     96 
     97         if (!(pw = memget(sizeof *pw))) {
     98                 errno = ENOMEM;
     99                 return (NULL);
    100         }
    101         memset(pw, 0x5e, sizeof *pw);
    102         if (!(pvt = memget(sizeof *pvt))) {
    103                 memput(pw, sizeof *pw);
    104                 errno = ENOMEM;
    105                 return (NULL);
    106         }
    107         memset(pvt, 0, sizeof *pvt);
    108 	pvt->needrewind = 1;
    109 	pvt->nis_domain = ((struct nis_p *)this->private)->domain;
    110 	pw->private = pvt;
    111 	pw->close = pw_close;
    112 	pw->next = pw_next;
    113 	pw->byname = pw_byname;
    114 	pw->byuid = pw_byuid;
    115 	pw->rewind = pw_rewind;
    116 	pw->minimize = pw_minimize;
    117 	pw->res_get = NULL;
    118 	pw->res_set = NULL;
    119 	return (pw);
    120 }
    121 
    122 /* Methods */
    123 
    124 static void
    125 pw_close(struct irs_pw *this) {
    126 	struct pvt *pvt = (struct pvt *)this->private;
    127 
    128 	if (pvt->pwbuf)
    129 		free(pvt->pwbuf);
    130 	nisfree(pvt, do_all);
    131 	memput(pvt, sizeof *pvt);
    132 	memput(this, sizeof *this);
    133 }
    134 
    135 static struct passwd *
    136 pw_next(struct irs_pw *this) {
    137 	struct pvt *pvt = (struct pvt *)this->private;
    138 	struct passwd *rval;
    139 	int r;
    140 
    141 	do {
    142 		if (pvt->needrewind) {
    143 			nisfree(pvt, do_all);
    144 			r = yp_first(pvt->nis_domain, passwd_byname,
    145 				     &pvt->curkey_data, &pvt->curkey_len,
    146 				     &pvt->curval_data, &pvt->curval_len);
    147 			pvt->needrewind = 0;
    148 		} else {
    149 			char *newkey_data;
    150 			int newkey_len;
    151 
    152 			nisfree(pvt, do_val);
    153 			r = yp_next(pvt->nis_domain, passwd_byname,
    154 				    pvt->curkey_data, pvt->curkey_len,
    155 				    &newkey_data, &newkey_len,
    156 				    &pvt->curval_data, &pvt->curval_len);
    157 			nisfree(pvt, do_key);
    158 			pvt->curkey_data = newkey_data;
    159 			pvt->curkey_len = newkey_len;
    160 		}
    161 		if (r != 0) {
    162 			errno = ENOENT;
    163 			return (NULL);
    164 		}
    165 		rval = makepasswdent(this);
    166 	} while (rval == NULL);
    167 	return (rval);
    168 }
    169 
    170 static struct passwd *
    171 pw_byname(struct irs_pw *this, const char *name) {
    172 	struct pvt *pvt = (struct pvt *)this->private;
    173 	int r;
    174 	char *tmp;
    175 
    176 	nisfree(pvt, do_val);
    177 	DE_CONST(name, tmp);
    178 	r = yp_match(pvt->nis_domain, passwd_byname, tmp, strlen(tmp),
    179 		     &pvt->curval_data, &pvt->curval_len);
    180 	if (r != 0) {
    181 		errno = ENOENT;
    182 		return (NULL);
    183 	}
    184 	return (makepasswdent(this));
    185 }
    186 
    187 static struct passwd *
    188 pw_byuid(struct irs_pw *this, uid_t uid) {
    189 	struct pvt *pvt = (struct pvt *)this->private;
    190 	char tmp[sizeof "4294967295"];
    191 	int r;
    192 
    193 	nisfree(pvt, do_val);
    194 	(void) sprintf(tmp, "%u", (unsigned int)uid);
    195 	r = yp_match(pvt->nis_domain, passwd_byuid, tmp, strlen(tmp),
    196 		     &pvt->curval_data, &pvt->curval_len);
    197 	if (r != 0) {
    198 		errno = ENOENT;
    199 		return (NULL);
    200 	}
    201 	return (makepasswdent(this));
    202 }
    203 
    204 static void
    205 pw_rewind(struct irs_pw *this) {
    206 	struct pvt *pvt = (struct pvt *)this->private;
    207 
    208 	pvt->needrewind = 1;
    209 }
    210 
    211 static void
    212 pw_minimize(struct irs_pw *this) {
    213 	UNUSED(this);
    214 	/* NOOP */
    215 }
    216 
    217 /* Private */
    218 
    219 static struct passwd *
    220 makepasswdent(struct irs_pw *this) {
    221 	struct pvt *pvt = (struct pvt *)this->private;
    222 	char *cp;
    223 
    224 	memset(&pvt->passwd, 0, sizeof pvt->passwd);
    225 	if (pvt->pwbuf)
    226 		free(pvt->pwbuf);
    227 	pvt->pwbuf = pvt->curval_data;
    228 	pvt->curval_data = NULL;
    229 
    230 	cp = pvt->pwbuf;
    231 	pvt->passwd.pw_name = cp;
    232 	if (!(cp = strchr(cp, ':')))
    233 		goto cleanup;
    234 #ifdef HAS_PW_CLASS
    235 	pvt->passwd.pw_class = cp;	/*%< Needs to point at a \0. */
    236 #endif
    237 	*cp++ = '\0';
    238 
    239 	pvt->passwd.pw_passwd = cp;
    240 	if (!(cp = strchr(cp, ':')))
    241 		goto cleanup;
    242 	*cp++ = '\0';
    243 
    244 	pvt->passwd.pw_uid = atoi(cp);
    245 	if (!(cp = strchr(cp, ':')))
    246 		goto cleanup;
    247 	*cp++ = '\0';
    248 
    249 	pvt->passwd.pw_gid = atoi(cp);
    250 	if (!(cp = strchr(cp, ':')))
    251 		goto cleanup;
    252 	*cp++ = '\0';
    253 
    254 	pvt->passwd.pw_gecos = cp;
    255 	if (!(cp = strchr(cp, ':')))
    256 		goto cleanup;
    257 	*cp++ = '\0';
    258 
    259 	pvt->passwd.pw_dir = cp;
    260 	if (!(cp = strchr(cp, ':')))
    261 		goto cleanup;
    262 	*cp++ = '\0';
    263 
    264 	pvt->passwd.pw_shell = cp;
    265 
    266 	if ((cp = strchr(cp, '\n')) != NULL)
    267 		*cp = '\0';
    268 
    269 	return (&pvt->passwd);
    270 
    271  cleanup:
    272 	free(pvt->pwbuf);
    273 	pvt->pwbuf = NULL;
    274 	return (NULL);
    275 }
    276 
    277 static void
    278 nisfree(struct pvt *pvt, enum do_what do_what) {
    279 	if ((do_what & do_key) && pvt->curkey_data) {
    280 		free(pvt->curkey_data);
    281 		pvt->curkey_data = NULL;
    282 	}
    283 	if ((do_what & do_val) && pvt->curval_data) {
    284 		free(pvt->curval_data);
    285 		pvt->curval_data = NULL;
    286 	}
    287 }
    288 
    289 #endif /* WANT_IRS_PW && WANT_IRS_NIS */
    290 /*! \file */
    291