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 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
33 */
34
35 #include <stdlib.h>
36 #include <dirent.h>
37 #include <string.h>
38 #include <malloc.h>
39 #include "ypsym.h"
40 #include "ypdefs.h"
41
42 /* Use N2L version of DBM calls */
43 #include "shim_hooks.h"
44
45 USE_YP_MASTER_NAME
46 USE_YP_LAST_MODIFIED
47 USE_YPDBPATH
48 USE_YP_SECURE
49 USE_DBM
50
51 #include <ctype.h>
52
53 static DBM *cur_fdb; /* will be passwd back up by ypset_current_map */
54 static enum { UNKNOWN, SECURE, PUBLIC } current_map_access = UNKNOWN;
55 static char map_owner[MAX_MASTER_NAME + 1];
56
57 extern unsigned int ypcheck_domain();
58 int check_secure_net_ti(struct netbuf *caller, char *ypname);
59
60 /*
61 * The retrieves the order number of a named map from the order number datum
62 * in the map data base.
63 */
64 bool
ypget_map_order(char * map,char * domain,uint_t * order)65 ypget_map_order(char *map, char *domain, uint_t *order)
66 {
67 datum key;
68 datum val;
69 char toconvert[MAX_ASCII_ORDER_NUMBER_LENGTH + 1];
70 uint_t error;
71 DBM *fdb;
72
73 if ((fdb = ypset_current_map(map, domain, &error)) != NULL) {
74 key.dptr = yp_last_modified;
75 key.dsize = yp_last_modified_sz;
76 val = dbm_fetch(fdb, key);
77
78 if (val.dptr != (char *)NULL) {
79
80 if (val.dsize > MAX_ASCII_ORDER_NUMBER_LENGTH) {
81 return (FALSE);
82 }
83
84 /*
85 * This is getting recopied here because val.dptr
86 * points to static memory owned by the dbm package,
87 * and we have no idea whether numeric characters
88 * follow the order number characters, nor whether
89 * the mess is null-terminated at all.
90 */
91
92 memcpy(toconvert, val.dptr, val.dsize);
93 toconvert[val.dsize] = '\0';
94 *order = (unsigned long) atol(toconvert);
95 return (TRUE);
96 } else {
97 return (FALSE);
98 }
99
100 } else {
101 return (FALSE);
102 }
103 }
104
105 /*
106 * The retrieves the master server name of a named map from the master datum
107 * in the map data base.
108 */
109 bool
ypget_map_master(char ** owner,DBM * fdb)110 ypget_map_master(char **owner, DBM *fdb)
111 {
112 datum key;
113 datum val;
114
115 key.dptr = yp_master_name;
116 key.dsize = yp_master_name_sz;
117 val = dbm_fetch(fdb, key);
118
119 if (val.dptr != (char *)NULL) {
120
121 if (val.dsize > MAX_MASTER_NAME) {
122 return (FALSE);
123 }
124
125 /*
126 * This is getting recopied here because val.dptr
127 * points to static memory owned by the dbm package.
128 */
129 memcpy(map_owner, val.dptr, val.dsize);
130 map_owner[val.dsize] = '\0';
131 *owner = map_owner;
132 return (TRUE);
133 } else {
134 return (FALSE);
135 }
136 }
137
138 /*
139 * This makes a map into the current map, and calls dbminit on that map
140 * and returns the DBM pointer to the map. Procedures called by
141 * ypserv dispatch routine would use this pointer for successive
142 * ndbm operations. Returns an YP_xxxx error code in error if FALSE.
143 */
144 DBM *
ypset_current_map(char * map,char * domain,uint_t * error)145 ypset_current_map(char *map, char *domain, uint_t *error)
146 {
147 char mapname[MAXNAMLEN + 1];
148 int lenm, lend;
149
150 /* Do not allow any path as a domain name or a map name. */
151 if (!map || ((lenm = (int)strlen(map)) == 0) || (lenm > YPMAXMAP) ||
152 !domain || ((lend = (int)strlen(domain)) == 0) ||
153 (lend > YPMAXDOMAIN) || (strchr(map, '/') != NULL) ||
154 (strchr(domain, '/') != NULL)) {
155 *error = YP_BADARGS;
156 return (FALSE);
157 }
158
159 if (FALSE == ypmkfilename(domain, map, mapname))
160 return (FALSE);
161
162 if ((cur_fdb) && (strcmp(mapname, get_map_name(cur_fdb)) == 0)) {
163 return (cur_fdb);
164 }
165
166 /* If there was a previous open map close it */
167 if (NULL != cur_fdb)
168 dbm_close(cur_fdb);
169
170 /* Set the map access as "unknown" as the new map has not been loaded */
171 current_map_access = UNKNOWN;
172
173 /* All the map locking is now handled inside the dbm_open shim */
174 if ((cur_fdb = dbm_open(mapname, O_RDWR, 0644)) != NULL) {
175 return (cur_fdb);
176 }
177
178 if (ypcheck_domain(domain)) {
179
180 if (ypcheck_map_existence(mapname)) {
181 *error = YP_BADDB;
182 } else {
183 *error = YP_NOMAP;
184 }
185
186 } else {
187 *error = YP_NODOM;
188 }
189
190 return (NULL);
191 }
192
193 /*
194 * This checks to see if there is a current map, and, if there is, does a
195 * dbmclose on it and sets the current map name and its DBM ptr to null.
196 */
197 void
ypclr_current_map(void)198 ypclr_current_map(void)
199 {
200 if (cur_fdb != NULL) {
201 (void) dbm_close(cur_fdb);
202 cur_fdb = NULL;
203 }
204 current_map_access = UNKNOWN;
205 }
206
207 /*
208 * Checks to see if caller has permission to query the current map (as
209 * set by ypset_current_map()). Returns TRUE if access is granted and
210 * FALSE otherwise. If FALSE then sets *error to YP_xxxxxxxx.
211 */
212 bool
yp_map_access(SVCXPRT * transp,uint_t * error,DBM * fdb)213 yp_map_access(SVCXPRT *transp, uint_t *error, DBM *fdb)
214 {
215 char *ypname = "ypserv";
216 struct netbuf *nbuf;
217 sa_family_t af;
218 in_port_t port;
219
220 nbuf = svc_getrpccaller(transp);
221 af = ((struct sockaddr_storage *)nbuf->buf)->ss_family;
222 if (af != AF_INET && af != AF_INET6)
223 return (FALSE);
224
225 if (!(check_secure_net_ti(nbuf, ypname))) {
226 *error = YP_NOMAP;
227 return (FALSE);
228 }
229
230 /* XXX - I expect that this won't happen much */
231 if (current_map_access == PUBLIC) {
232 return (TRUE);
233 }
234
235 if (af == AF_INET6) {
236 port = ntohs(((struct sockaddr_in6 *)nbuf->buf)->sin6_port);
237 } else {
238 port = ntohs(((struct sockaddr_in *)nbuf->buf)->sin_port);
239 }
240 if (port < IPPORT_RESERVED) {
241 return (TRUE);
242 }
243
244 if (current_map_access == UNKNOWN) {
245 datum key;
246 datum val;
247
248 key.dptr = yp_secure;
249 key.dsize = yp_secure_sz;
250 val = dbm_fetch(fdb, key);
251 if (val.dptr == (char *)NULL) {
252 current_map_access = PUBLIC;
253 return (TRUE);
254 }
255 current_map_access = SECURE;
256 }
257
258 /* current_map_access == SECURE and non-priviledged caller */
259 *error = YP_NOMAP;
260 return (FALSE);
261 }
262