1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * getpwent.c 24 * 25 * Copyright (c) 1988-1992 Sun Microsystems Inc 26 * All Rights Reserved. 27 * 28 * lib/nsswitch/compat/getpwent.c -- name-service-switch backend for getpwnam() 29 * et al that does 4.x compatibility. It looks in /etc/passwd; if it finds 30 * passwd entries there that begin with "+" or "-", it consults other 31 * services. By default it uses NIS (YP), but the user can override this 32 * with a "passwd_compat" entry in /etc/nsswitch.conf, e.g. 33 * passwd_compat: nisplus 34 * 35 * This code tries to produce the same results as the 4.x code, even when 36 * the latter seems ill thought-out (mostly in the handling of netgroups, 37 * "-", and the combination thereof). Bug-compatible, in other words. 38 * Though we do try to be more reasonable about the format of "+" and "-" 39 * entries here, i.e. you don't have to pad them with spurious colons and 40 * bogus uid/gid values. 41 * 42 * Caveats: 43 * - More than one source may be specified, with the usual switch semantics, 44 * but having multiple sources here is definitely odd. 45 * - People who recursively specify "compat" deserve what they get. 46 * - Entries that begin with "+@" or "-@" are interpreted using 47 * getnetgrent() and innetgr(), which use the "netgroup" entry in 48 * /etc/nsswitch.conf. If the sources for "passwd_compat" and "netgroup" 49 * differ, everything should work fine, but the semantics will be pretty 50 * confusing. 51 */ 52 53 #pragma ident "%Z%%M% %I% %E% SMI" 54 55 #include <pwd.h> 56 #include <shadow.h> /* For PASSWD (pathname to passwd file) */ 57 #include <stdlib.h> 58 #include <strings.h> 59 #include "compat_common.h" 60 61 static DEFINE_NSS_DB_ROOT(db_root); 62 63 void 64 _nss_initf_passwd_compat(p) 65 nss_db_params_t *p; 66 { 67 p->name = NSS_DBNAM_PASSWD; 68 p->config_name = NSS_DBNAM_PASSWD_COMPAT; 69 p->default_config = NSS_DEFCONF_PASSWD_COMPAT; 70 } 71 72 static const char * 73 get_pwname(argp) 74 nss_XbyY_args_t *argp; 75 { 76 struct passwd *p = (struct passwd *)argp->returnval; 77 78 return (p->pw_name); 79 } 80 81 static int 82 check_pwname(argp) 83 nss_XbyY_args_t *argp; 84 { 85 struct passwd *p = (struct passwd *)argp->returnval; 86 87 return (strcmp(p->pw_name, argp->key.name) == 0); 88 } 89 90 static nss_status_t 91 getbyname(be, a) 92 compat_backend_ptr_t be; 93 void *a; 94 { 95 nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a; 96 97 return (_nss_compat_XY_all(be, argp, 98 check_pwname, NSS_DBOP_PASSWD_BYNAME)); 99 } 100 101 static int 102 check_pwuid(argp) 103 nss_XbyY_args_t *argp; 104 { 105 struct passwd *p = (struct passwd *)argp->returnval; 106 107 return (p->pw_uid == argp->key.uid); 108 } 109 110 static nss_status_t 111 getbyuid(be, a) 112 compat_backend_ptr_t be; 113 void *a; 114 { 115 nss_XbyY_args_t *argp = (nss_XbyY_args_t *) a; 116 117 return (_nss_compat_XY_all(be, argp, 118 check_pwuid, NSS_DBOP_PASSWD_BYUID)); 119 } 120 121 /*ARGSUSED*/ 122 static int 123 merge_pwents(be, argp, fields) 124 compat_backend_ptr_t be; 125 nss_XbyY_args_t *argp; 126 const char **fields; 127 { 128 struct passwd *pw = (struct passwd *)argp->buf.result; 129 char *buf = malloc(NSS_LINELEN_PASSWD); 130 char *s; 131 int parsestat; 132 133 if (buf == 0) { 134 return (NSS_STR_PARSE_PARSE); 135 /* Really "out of memory", but PARSE_PARSE will have to do */ 136 } 137 /* 138 * Don't allow overriding of 139 * - username 140 * - uid 141 * - gid 142 * That's what the SunOS 4.x code did; who are we to question it... 143 */ 144 s = buf; 145 sprintf(s, "%s:", pw->pw_name); 146 s += strlen(s); 147 if (fields[1] != 0) { 148 strcpy(s, fields[1]); 149 } else { 150 strcpy(s, pw->pw_passwd); 151 if (pw->pw_age != 0) { 152 s += strlen(s); 153 /* ====> Does this do the right thing? */ 154 sprintf(s, ",%s", pw->pw_age); 155 } 156 } 157 s += strlen(s); 158 sprintf(s, ":%d:%d:%s:%s:%s", 159 pw->pw_uid, 160 pw->pw_gid, 161 fields[4] != 0 ? fields[4] : pw->pw_gecos, 162 fields[5] != 0 ? fields[5] : pw->pw_dir, 163 fields[6] != 0 ? fields[6] : pw->pw_shell); 164 s += strlen(s); 165 parsestat = (*argp->str2ent)(buf, s - buf, 166 argp->buf.result, 167 argp->buf.buffer, 168 argp->buf.buflen); 169 free(buf); 170 return (parsestat); 171 } 172 173 static compat_backend_op_t passwd_ops[] = { 174 _nss_compat_destr, 175 _nss_compat_endent, 176 _nss_compat_setent, 177 _nss_compat_getent, 178 getbyname, 179 getbyuid 180 }; 181 182 /*ARGSUSED*/ 183 nss_backend_t * 184 _nss_compat_passwd_constr(dummy1, dummy2, dummy3) 185 const char *dummy1, *dummy2, *dummy3; 186 { 187 return (_nss_compat_constr(passwd_ops, 188 sizeof (passwd_ops) / sizeof (passwd_ops[0]), 189 PASSWD, 190 NSS_LINELEN_PASSWD, 191 &db_root, 192 _nss_initf_passwd_compat, 193 1, 194 get_pwname, 195 merge_pwents)); 196 } 197