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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 * Portions of this source code were derived from Berkeley
30 * 4.3 BSD under license from the Regents of the University of
34 * ==== hack-attack: possibly MT-safe but definitely not MT-hot.
35 * ==== turn this into a real switch frontend and backends
37 * Well, at least the API doesn't involve pointers-to-static.
41 * netname utility routines (getnetname, user2netname, host2netname).
43 * Convert from unix names (uid, gid) to network wide names.
44 * This module is operating system dependent!
45 * What we define here will work with any unix system that has adopted
46 * the Sun NIS domain architecture.
56 #include <sys/types.h>
60 #include <sys/param.h>
62 #include <rpcsvc/nis.h>
63 #include <rpcsvc/nis_dhext.h>
68 #ifndef MAXHOSTNAMELEN
69 #define MAXHOSTNAMELEN 256
76 * the value for NOBODY_UID is set by the SVID. The following define also
77 * appears in netnamer.c
80 #define NOBODY_UID 60001
82 extern int getdomainname();
83 extern int key_call();
85 static const char *OPSYS
= "unix";
88 * default publickey policy:
89 * publickey: nis [NOTFOUND = return] files
93 /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */
94 #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE}
96 static struct __nsw_lookup lookup_files
= {"files", DEF_ACTION
, NULL
, NULL
},
97 lookup_nis
= {"nis", DEF_ACTION
, NULL
, &lookup_files
};
98 static struct __nsw_switchconfig publickey_default
=
99 {0, "publickey", 2, &lookup_nis
};
101 static mutex_t serialize_netname
= ERRORCHECKMUTEX
;
104 #define MAXIPRINT (11) /* max length of printed integer */
107 * Convert unix cred to network-name by concatenating the
108 * 3 pieces of information <opsys type> <uid> <domain>.
112 user2netname_nis(int *err
, char netname
[MAXNETNAMELEN
+ 1], uid_t uid
,
117 if (domain
== NULL
) {
118 if (__rpc_get_default_domain(&dfltdom
) != 0) {
119 *err
= __NSW_UNAVAIL
;
124 if ((strlen(domain
) + OPSYS_LEN
+ 3 + MAXIPRINT
) >
125 (size_t)MAXNETNAMELEN
) {
126 *err
= __NSW_UNAVAIL
;
129 (void) snprintf(netname
, MAXNETNAMELEN
+ 1,
130 "%s.%d@%s", OPSYS
, (int)uid
, domain
);
132 if (netname
[i
-1] == '.')
134 *err
= __NSW_SUCCESS
;
139 * Figure out my fully qualified network name
142 getnetname(char name
[MAXNETNAMELEN
+ 1])
148 return (host2netname(name
, NULL
, NULL
));
149 return (user2netname(name
, uid
, NULL
));
154 * Figure out the fully qualified network name for the given uid.
155 * This is a private interface.
158 __getnetnamebyuid(char name
[MAXNETNAMELEN
+ 1], uid_t uid
)
161 return (host2netname(name
, NULL
, NULL
));
162 return (user2netname(name
, uid
, NULL
));
166 * Convert unix cred to network-name
168 * It uses the publickey policy in the /etc/nsswitch.conf file
169 * (Unless the netname is "nobody", which is special cased).
170 * If there is no publickey policy in /etc/nsswitch.conf,
171 * the default publickey policy is used, which is
172 * publickey: nis [NOTFOUND=return] files
173 * Note that for the non-nisplus case, there is no failover
174 * so only the first entry would be relevant for those cases.
177 user2netname(char netname
[MAXNETNAMELEN
+ 1], const uid_t uid
,
180 struct __nsw_switchconfig
*conf
;
181 struct __nsw_lookup
*look
;
182 int needfree
= 1, res
= 0;
183 enum __nsw_parse_err perr
;
187 * Take care of the special case of "nobody". If the uid is
188 * the value assigned by the SVID for nobody, return the string
192 if (uid
== NOBODY_UID
) {
193 (void) strlcpy(netname
, "nobody", sizeof (netname
));
197 netname
[0] = '\0'; /* make null first (no need for memset) */
199 if (mutex_lock(&serialize_netname
) == EDEADLK
) {
201 * This thread already holds this lock. This scenario
202 * occurs when a process requires a netname which
203 * itself requires a netname to look up. As we clearly
204 * can't continue like this we return 'nobody'.
206 (void) strlcpy(netname
, "nobody", sizeof (netname
));
210 conf
= __nsw_getconfig("publickey", &perr
);
212 conf
= &publickey_default
;
216 for (look
= conf
->lookups
; look
; look
= look
->next
) {
217 /* ldap, nis, and files all do the same thing. */
218 if (strcmp(look
->service_name
, "ldap") == 0 ||
219 strcmp(look
->service_name
, "nis") == 0 ||
220 strcmp(look
->service_name
, "files") == 0)
221 res
= user2netname_nis(&err
,
222 netname
, uid
, (char *)domain
);
225 "user2netname: unknown nameservice \
226 for publickey info '%s'\n",
230 switch (look
->actions
[err
]) {
231 case __NSW_CONTINUE
:
235 (void) __nsw_freeconfig(conf
);
236 (void) mutex_unlock(&serialize_netname
);
240 "user2netname: Unknown action for nameservice '%s'",
245 (void) __nsw_freeconfig(conf
);
246 (void) mutex_unlock(&serialize_netname
);
252 * Convert host to network-name
253 * This routine returns following netnames given the host and domain
254 * arguments defined below: (domainname=y.z)
256 * host domain netname
257 * ---- ------ -------
258 * - - unix.m@y.z (hostname=m)
259 * - a.b unix.m@a.b (hostname=m)
260 * - - unix.m@y.z (hostname=m.w.x)
261 * - a.b unix.m@a.b (hostname=m.w.x)
265 * h.w.x a.b unix.h@a.b
268 host2netname(char netname
[MAXNETNAMELEN
+ 1], const char *host
,
272 char hostname
[MAXHOSTNAMELEN
+ 1];
273 char domainname
[MAXHOSTNAMELEN
+ 1];
278 netname
[0] = '\0'; /* make null first (no need for memset) */
281 (void) strncpy(hostname
, nis_local_host(), sizeof (hostname
));
282 p
= (char *)strchr(hostname
, '.');
285 /* if no domain passed, use tail of nis_local_host() */
286 if (domain
== NULL
) {
292 if (len
>= sizeof (hostname
)) {
295 (void) strcpy(hostname
, host
);
298 dot_in_host
= (char *)strchr(hostname
, '.');
299 if (domain
== NULL
) {
302 p
= (char *)nis_domain_of(hostname
);
304 if (len
>= sizeof (domainname
)) {
307 (void) strcpy(domainname
, p
);
309 domainname
[0] = NULL
;
310 if (getdomainname(domainname
, MAXHOSTNAMELEN
) < 0)
314 len
= strlen(domain
);
315 if (len
>= sizeof (domainname
)) {
318 (void) strcpy(domainname
, domain
);
321 i
= strlen(domainname
);
325 if (domainname
[i
- 1] == '.')
326 domainname
[i
- 1] = 0;
328 if (dot_in_host
) { /* strip off rest of name */
332 if ((strlen(domainname
) + strlen(hostname
) + OPSYS_LEN
+ 3)
333 > (size_t)MAXNETNAMELEN
) {
337 (void) snprintf(netname
, MAXNETNAMELEN
+ 1,
338 "%s.%s@%s", OPSYS
, hostname
, domainname
);