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.
54 #include <sys/types.h>
58 #include <sys/param.h>
60 #include <rpcsvc/nis.h>
61 #include <rpcsvc/nis_dhext.h>
66 #ifndef MAXHOSTNAMELEN
67 #define MAXHOSTNAMELEN 256
74 * the value for NOBODY_UID is set by the SVID. The following define also
75 * appears in netnamer.c
78 #define NOBODY_UID 60001
80 extern int getdomainname();
81 extern int key_call();
83 static const char *OPSYS
= "unix";
86 * default publickey policy:
87 * publickey: nis [NOTFOUND = return] files
91 /* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */
92 #define DEF_ACTION {__NSW_RETURN, __NSW_RETURN, __NSW_CONTINUE, __NSW_CONTINUE}
94 static struct __nsw_lookup lookup_files
= {"files", DEF_ACTION
, NULL
, NULL
},
95 lookup_nis
= {"nis", DEF_ACTION
, NULL
, &lookup_files
};
96 static struct __nsw_switchconfig publickey_default
=
97 {0, "publickey", 2, &lookup_nis
};
99 static mutex_t serialize_netname
= ERRORCHECKMUTEX
;
102 #define MAXIPRINT (11) /* max length of printed integer */
105 * Convert unix cred to network-name by concatenating the
106 * 3 pieces of information <opsys type> <uid> <domain>.
110 user2netname_nis(int *err
, char netname
[MAXNETNAMELEN
+ 1], uid_t uid
,
115 if (domain
== NULL
) {
116 if (__rpc_get_default_domain(&dfltdom
) != 0) {
117 *err
= __NSW_UNAVAIL
;
122 if ((strlen(domain
) + OPSYS_LEN
+ 3 + MAXIPRINT
) >
123 (size_t)MAXNETNAMELEN
) {
124 *err
= __NSW_UNAVAIL
;
127 (void) snprintf(netname
, MAXNETNAMELEN
+ 1,
128 "%s.%d@%s", OPSYS
, (int)uid
, domain
);
130 if (netname
[i
-1] == '.')
132 *err
= __NSW_SUCCESS
;
137 * Figure out my fully qualified network name
140 getnetname(char name
[MAXNETNAMELEN
+ 1])
146 return (host2netname(name
, NULL
, NULL
));
147 return (user2netname(name
, uid
, NULL
));
152 * Figure out the fully qualified network name for the given uid.
153 * This is a private interface.
156 __getnetnamebyuid(char name
[MAXNETNAMELEN
+ 1], uid_t uid
)
159 return (host2netname(name
, NULL
, NULL
));
160 return (user2netname(name
, uid
, NULL
));
164 * Convert unix cred to network-name
166 * It uses the publickey policy in the /etc/nsswitch.conf file
167 * (Unless the netname is "nobody", which is special cased).
168 * If there is no publickey policy in /etc/nsswitch.conf,
169 * the default publickey policy is used, which is
170 * publickey: nis [NOTFOUND=return] files
171 * Note that for the non-nisplus case, there is no failover
172 * so only the first entry would be relevant for those cases.
175 user2netname(char netname
[MAXNETNAMELEN
+ 1], const uid_t uid
,
178 struct __nsw_switchconfig
*conf
;
179 struct __nsw_lookup
*look
;
180 int needfree
= 1, res
= 0;
181 enum __nsw_parse_err perr
;
185 * Take care of the special case of "nobody". If the uid is
186 * the value assigned by the SVID for nobody, return the string
190 if (uid
== NOBODY_UID
) {
191 (void) strlcpy(netname
, "nobody", MAXNETNAMELEN
+ 1);
195 netname
[0] = '\0'; /* make null first (no need for memset) */
197 if (mutex_lock(&serialize_netname
) == EDEADLK
) {
199 * This thread already holds this lock. This scenario
200 * occurs when a process requires a netname which
201 * itself requires a netname to look up. As we clearly
202 * can't continue like this we return 'nobody'.
204 (void) strlcpy(netname
, "nobody", MAXNETNAMELEN
+ 1);
208 conf
= __nsw_getconfig("publickey", &perr
);
210 conf
= &publickey_default
;
214 for (look
= conf
->lookups
; look
; look
= look
->next
) {
215 /* ldap, nis, and files all do the same thing. */
216 if (strcmp(look
->service_name
, "ldap") == 0 ||
217 strcmp(look
->service_name
, "nis") == 0 ||
218 strcmp(look
->service_name
, "files") == 0)
219 res
= user2netname_nis(&err
,
220 netname
, uid
, (char *)domain
);
223 "user2netname: unknown nameservice \
224 for publickey info '%s'\n",
228 switch (look
->actions
[err
]) {
229 case __NSW_CONTINUE
:
233 (void) __nsw_freeconfig(conf
);
234 (void) mutex_unlock(&serialize_netname
);
238 "user2netname: Unknown action for nameservice '%s'",
243 (void) __nsw_freeconfig(conf
);
244 (void) mutex_unlock(&serialize_netname
);
250 * Convert host to network-name
251 * This routine returns following netnames given the host and domain
252 * arguments defined below: (domainname=y.z)
254 * host domain netname
255 * ---- ------ -------
256 * - - unix.m@y.z (hostname=m)
257 * - a.b unix.m@a.b (hostname=m)
258 * - - unix.m@y.z (hostname=m.w.x)
259 * - a.b unix.m@a.b (hostname=m.w.x)
263 * h.w.x a.b unix.h@a.b
266 host2netname(char netname
[MAXNETNAMELEN
+ 1], const char *host
,
270 char hostname
[MAXHOSTNAMELEN
+ 1];
271 char domainname
[MAXHOSTNAMELEN
+ 1];
276 netname
[0] = '\0'; /* make null first (no need for memset) */
279 (void) strncpy(hostname
, nis_local_host(), sizeof (hostname
));
280 p
= (char *)strchr(hostname
, '.');
283 /* if no domain passed, use tail of nis_local_host() */
284 if (domain
== NULL
) {
290 if (len
>= sizeof (hostname
)) {
293 (void) strcpy(hostname
, host
);
296 dot_in_host
= (char *)strchr(hostname
, '.');
297 if (domain
== NULL
) {
300 p
= (char *)nis_domain_of(hostname
);
302 if (len
>= sizeof (domainname
)) {
305 (void) strcpy(domainname
, p
);
307 domainname
[0] = '\0';
308 if (getdomainname(domainname
, MAXHOSTNAMELEN
) < 0)
312 len
= strlen(domain
);
313 if (len
>= sizeof (domainname
)) {
316 (void) strcpy(domainname
, domain
);
319 i
= strlen(domainname
);
323 if (domainname
[i
- 1] == '.')
324 domainname
[i
- 1] = 0;
326 if (dot_in_host
) { /* strip off rest of name */
330 if ((strlen(domainname
) + strlen(hostname
) + OPSYS_LEN
+ 3)
331 > (size_t)MAXNETNAMELEN
) {
335 (void) snprintf(netname
, MAXNETNAMELEN
+ 1,
336 "%s.%s@%s", OPSYS
, hostname
, domainname
);