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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * nis/getpwnam.c -- "nis" backend for nsswitch "passwd" database
26 */
27
28 #include <pwd.h>
29 #include "nis_common.h"
30
31 static nss_status_t
getbyname(be,a)32 getbyname(be, a)
33 nis_backend_ptr_t be;
34 void *a;
35 {
36 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
37
38 return (_nss_nis_lookup(be, argp, 0,
39 "passwd.byname", argp->key.name, 0));
40 }
41
42 static nss_status_t
getbyuid(be,a)43 getbyuid(be, a)
44 nis_backend_ptr_t be;
45 void *a;
46 {
47 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)a;
48 char uidstr[12]; /* More than enough */
49
50 if (argp->key.uid > MAXUID)
51 return (NSS_NOTFOUND);
52 (void) snprintf(uidstr, 12, "%u", argp->key.uid);
53 return (_nss_nis_lookup(be, argp, 0, "passwd.byuid", uidstr, 0));
54 }
55
56 /*
57 * Validates passwd entry replacing uid/gid > MAXUID by ID_NOBODY.
58 */
59 int
validate_passwd_ids(char ** linepp,int * linelenp,int allocbuf)60 validate_passwd_ids(char **linepp, int *linelenp, int allocbuf)
61 {
62 char *linep, *limit, *uidp, *gidp, *newline;
63 uid_t uid;
64 gid_t gid;
65 ulong_t uidl, gidl;
66 int olduidlen, oldgidlen, idlen;
67 int linelen = *linelenp, newlinelen;
68
69 linep = *linepp;
70 limit = linep + linelen;
71
72 /* +/- entries valid for compat source only */
73 if (linelen == 0 || *linep == '+' || *linep == '-')
74 return (NSS_STR_PARSE_SUCCESS);
75
76 while (linep < limit && *linep++ != ':') /* skip username */
77 continue;
78 while (linep < limit && *linep++ != ':') /* skip password */
79 continue;
80 if (linep == limit)
81 return (NSS_STR_PARSE_PARSE);
82
83 uidp = linep;
84 uidl = strtoul(uidp, (char **)&linep, 10); /* grab uid */
85 olduidlen = linep - uidp;
86 if (++linep >= limit || olduidlen == 0)
87 return (NSS_STR_PARSE_PARSE);
88
89 gidp = linep;
90 gidl = strtoul(gidp, (char **)&linep, 10); /* grab gid */
91 oldgidlen = linep - gidp;
92 if (linep >= limit || oldgidlen == 0)
93 return (NSS_STR_PARSE_PARSE);
94
95 if (uidl <= MAXUID && gidl <= MAXUID)
96 return (NSS_STR_PARSE_SUCCESS);
97 uid = (uidl > MAXUID) ? UID_NOBODY : (uid_t)uidl;
98 gid = (gidl > MAXUID) ? GID_NOBODY : (gid_t)gidl;
99
100 /* Check if we have enough space in the buffer */
101 idlen = snprintf(NULL, 0, "%u:%u", uid, gid);
102 newlinelen = linelen + idlen - olduidlen - oldgidlen - 1;
103 if (newlinelen > linelen) {
104 /* need a larger buffer */
105 if (!allocbuf || (newline = malloc(newlinelen + 1)) == NULL)
106 return (NSS_STR_PARSE_ERANGE);
107 /* Replace ephemeral ids by ID_NOBODY in the new buffer */
108 *(uidp - 1) = '\0';
109 (void) snprintf(newline, newlinelen + 1, "%s:%u:%u%s",
110 *linepp, uid, gid, linep);
111 free(*linepp);
112 *linepp = newline;
113 *linelenp = newlinelen;
114 return (NSS_STR_PARSE_SUCCESS);
115 }
116
117 /* Replace ephemeral ids by ID_NOBODY in the same buffer */
118 (void) bcopy(linep, uidp + idlen, limit - linep + 1);
119 (void) snprintf(uidp, idlen + 1, "%u:%u", uid, gid);
120 *(uidp + idlen) = ':'; /* restore : that was overwritten by snprintf */
121 *linelenp = newlinelen;
122 return (NSS_STR_PARSE_SUCCESS);
123 }
124
125 static nis_backend_op_t passwd_ops[] = {
126 _nss_nis_destr,
127 _nss_nis_endent,
128 _nss_nis_setent,
129 _nss_nis_getent_rigid,
130 getbyname,
131 getbyuid
132 };
133
134 /*ARGSUSED*/
135 nss_backend_t *
_nss_nis_passwd_constr(dummy1,dummy2,dummy3)136 _nss_nis_passwd_constr(dummy1, dummy2, dummy3)
137 const char *dummy1, *dummy2, dummy3;
138 {
139 return (_nss_nis_constr(passwd_ops,
140 sizeof (passwd_ops) / sizeof (passwd_ops[0]),
141 "passwd.byname"));
142 }
143