xref: /illumos-gate/usr/src/cmd/gss/gssd/gssd_generic.c (revision 1e56f352c1c208679012bca47d552e127f5b1072)
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  * Copyright (c) 1988-1997, by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <rpc/rpc.h>
30 #include <errno.h>
31 #include <syslog.h>
32 #include <rpc/nettype.h>
33 #include <netconfig.h>
34 #include <netdir.h>
35 #include <tiuser.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <rpc/svc.h>
39 #include <locale.h>
40 
41 extern int __rpc_negotiate_uid(int);
42 
43 /*
44  * The highest level interface for server creation.
45  * Copied from svc_generic.c and cmd/keyserv/key_generic.c, but adapted
46  * to work only for TPI_CLTS semantics, and to be called only once
47  * from gssd.c. Returns 1 (interface created) on success and 0
48  * (no interfaces created) on failure.
49  */
50 int
51 svc_create_local_service(dispatch, prognum, versnum, nettype, servname)
52 void (*dispatch) ();		/* Dispatch function */
53 u_long prognum;			/* Program number */
54 u_long versnum;			/* Version number */
55 char *nettype;			/* Networktype token */
56 char *servname;			/* name of the service */
57 {
58 	int num = 0;
59 	SVCXPRT *xprt;
60 	struct netconfig *nconf;
61 	struct t_bind *bind_addr;
62 	void *net;
63 	int fd;
64 	struct nd_hostserv ns;
65 	struct nd_addrlist *nas;
66 
67 	if ((net = __rpc_setconf(nettype)) == 0) {
68 		(void) syslog(LOG_ERR,
69 		gettext("svc_create: could not read netconfig database"));
70 		return (0);
71 	}
72 	while (nconf = __rpc_getconf(net)) {
73 		if ((strcmp(nconf->nc_protofmly, NC_LOOPBACK)) ||
74 				(nconf->nc_semantics != NC_TPI_COTS_ORD))
75 			continue;
76 
77 		if ((fd = t_open(nconf->nc_device, O_RDWR, NULL)) < 0) {
78 			(void) syslog(LOG_ERR,
79 			gettext("svc_create: %s: cannot open connection: %s"),
80 				nconf->nc_netid, t_errlist[t_errno]);
81 			break;
82 		}
83 
84 		/*
85 		 * Negotiate for returning the uid of the caller.
86 		 * This should be done before enabling the endpoint for
87 		 * service via t_bind() (called in svc_tli_create())
88 		 * so that requests to gssd contain the uid.
89 		 */
90 		if (__rpc_negotiate_uid(fd) != 0) {
91 			syslog(LOG_ERR,
92 			gettext("Could not negotiate for"
93 				" uid with loopback transport %s"),
94 				nconf->nc_netid);
95 			t_close(fd);
96 			break;
97 		}
98 
99 		/* LINTED pointer alignment */
100 		bind_addr = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR);
101 		if ((bind_addr == NULL)) {
102 			(void) t_close(fd);
103 			(void) syslog(LOG_ERR,
104 				gettext("svc_create: t_alloc failed\n"));
105 			break;
106 		}
107 		ns.h_host = HOST_SELF;
108 		ns.h_serv = servname;
109 		if (!netdir_getbyname(nconf, &ns, &nas)) {
110 			/* Copy the address */
111 			bind_addr->addr.len = nas->n_addrs->len;
112 			(void) memcpy(bind_addr->addr.buf, nas->n_addrs->buf,
113 				(int) nas->n_addrs->len);
114 			bind_addr->qlen = 8;
115 			netdir_free((char *) nas, ND_ADDRLIST);
116 		} else {
117 			(void) syslog(LOG_ERR,
118 			gettext("svc_create: no well known "
119 				"address for %s on %s\n"),
120 				servname, nconf->nc_netid);
121 			(void) t_free((char *) bind_addr, T_BIND);
122 			bind_addr = NULL;
123 		}
124 
125 		xprt = svc_tli_create(fd, nconf, bind_addr, 0, 0);
126 		if (bind_addr)
127 			(void) t_free((char *) bind_addr, T_BIND);
128 		if (xprt == NULL) {
129 			(void) t_close(fd);
130 			(void) syslog(LOG_ERR,
131 			    gettext("svc_create: svc_tli_create failed\n"));
132 			break;
133 		} else {
134 			(void) rpcb_unset(prognum, versnum, nconf);
135 			if (svc_reg(xprt, prognum, versnum, dispatch, nconf)
136 					== FALSE) {
137 				(void) syslog(LOG_ERR,
138 				gettext("svc_create: cannot"
139 					" register %d vers %d on %s"),
140 					prognum, versnum, nconf->nc_netid);
141 				SVC_DESTROY(xprt);	/* also t_closes fd */
142 				break;
143 			}
144 			num = 1;
145 			break;
146 		}
147 	}
148 	__rpc_endconf(net);
149 	return (num);
150 }
151