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) 1999 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <malloc.h>
36 #include <syslog.h>
37 #include <sys/tiuser.h>
38
39 #define ACCFILE "/var/yp/securenets"
40 #define MAXLINE 128
41
42 typedef union {
43 struct in_addr in4;
44 struct in6_addr in6;
45 } inaddr_t;
46
47 struct seclist {
48 sa_family_t af;
49 inaddr_t mask;
50 inaddr_t net;
51 struct seclist *next;
52 };
53
54 static int string2inaddr(char *, sa_family_t *, inaddr_t *);
55 static int addrequal(sa_family_t af, inaddr_t *laddr, inaddr_t *mask,
56 inaddr_t *caddr);
57
58 static struct seclist *slist;
59 static int nofile = 0;
60
61 void
get_secure_nets(char * daemon_name)62 get_secure_nets(char *daemon_name)
63 {
64 FILE *fp;
65 char strung[MAXLINE], nmask[MAXLINE], net[MAXLINE];
66 inaddr_t maskin, netin;
67 sa_family_t maskaf, netaf;
68 struct seclist *tmp1, *tmp2;
69 int items = 0, line = 0;
70 if (fp = fopen(ACCFILE, "r")) {
71 tmp1 = (struct seclist *) malloc(sizeof (struct seclist));
72 slist = tmp2 = tmp1;
73 while (fgets(strung, MAXLINE, fp)) {
74 line++;
75 if (strung[strlen(strung) - 1] != '\n') {
76 syslog(LOG_ERR|LOG_DAEMON,
77 "%s: %s line %d: too long\n",
78 daemon_name, ACCFILE, line);
79 exit(1);
80 }
81 if (strung[0] != '#') {
82 items++;
83 if (sscanf(strung,
84 "%46s%46s", nmask, net) < 2) {
85
86 syslog(LOG_ERR|LOG_DAEMON,
87 "%s: %s line %d: missing fields\n",
88 daemon_name, ACCFILE, line);
89 exit(1);
90 }
91 netaf = AF_UNSPEC;
92 if (! string2inaddr(net, &netaf, &netin)) {
93 syslog(LOG_ERR|LOG_DAEMON,
94 "%s: %s line %d: error in address\n",
95 daemon_name, ACCFILE, line);
96 exit(1);
97 }
98 maskaf = netaf;
99 if (! string2inaddr(nmask, &maskaf, &maskin) ||
100 maskaf != netaf) {
101 syslog(LOG_ERR|LOG_DAEMON,
102 "%s: %s line %d: error in netmask\n",
103 daemon_name, ACCFILE, line);
104 exit(1);
105 }
106 if (! addrequal(netaf, &netin, &maskin,
107 &netin)) {
108 syslog(LOG_ERR|LOG_DAEMON,
109 "%s: %s line %d: netmask does not match network\n",
110 daemon_name, ACCFILE, line);
111 exit(1);
112 }
113
114 tmp1->af = netaf;
115 tmp1->mask = maskin;
116 tmp1->net = netin;
117 tmp1->next = (struct seclist *)
118 malloc(sizeof (struct seclist));
119 tmp2 = tmp1;
120 tmp1 = tmp1->next;
121 }
122 }
123 tmp2->next = NULL;
124 /* if nothing to process, set nofile flag and free up memory */
125 if (items == 0) {
126 free(slist);
127 nofile = 1;
128 }
129 } else {
130 syslog(LOG_WARNING|LOG_DAEMON, "%s: no %s file\n",
131 daemon_name, ACCFILE);
132 nofile = 1;
133 }
134 }
135
136 int
check_secure_net_ti(struct netbuf * caller,char * ypname)137 check_secure_net_ti(struct netbuf *caller, char *ypname) {
138 struct seclist *tmp;
139 sa_family_t af;
140 inaddr_t addr;
141 char buf[INET6_ADDRSTRLEN];
142
143 if (nofile)
144 return (1);
145
146 af = ((struct sockaddr_storage *)caller->buf)->ss_family;
147 if (af == AF_INET) {
148 addr.in4 = ((struct sockaddr_in *)caller->buf)->sin_addr;
149 } else if (af == AF_INET6) {
150 addr.in6 = ((struct sockaddr_in6 *)caller->buf)->sin6_addr;
151 } else {
152 return (1);
153 }
154
155 tmp = slist;
156 while (tmp != NULL) {
157 if (af == tmp->af &&
158 addrequal(af, &tmp->net, &tmp->mask, &addr)) {
159 return (1);
160 }
161 tmp = tmp->next;
162 }
163 syslog(LOG_ERR|LOG_DAEMON, "%s: access denied for %s\n",
164 ypname, inet_ntop(af,
165 (af == AF_INET6) ? (void *)&addr.in6 :
166 (void *)&addr.in4, buf, sizeof (buf)));
167
168 return (0);
169 }
170
171
172 static int
string2inaddr(char * string,sa_family_t * af,inaddr_t * addr)173 string2inaddr(char *string, sa_family_t *af, inaddr_t *addr) {
174
175 sa_family_t stringaf = AF_UNSPEC;
176
177 stringaf = (strchr(string, ':') != 0) ? AF_INET6 : AF_INET;
178
179 if (*af != AF_UNSPEC && strcmp(string, "host") == 0) {
180 if (*af == AF_INET) {
181 string = "255.255.255.255";
182 stringaf = AF_INET;
183 } else if (*af == AF_INET6) {
184 string = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
185 stringaf = AF_INET6;
186 }
187 }
188
189 *af = stringaf;
190 if (inet_pton(*af, string, (*af == AF_INET6) ? (void *)&addr->in6 :
191 (void *)&addr->in4) != 1) {
192 return (0);
193 }
194
195 return (1);
196 }
197
198
199 static int
addrequal(sa_family_t af,inaddr_t * laddr,inaddr_t * mask,inaddr_t * caddr)200 addrequal(sa_family_t af, inaddr_t *laddr, inaddr_t *mask, inaddr_t *caddr) {
201
202 if (af == AF_INET6) {
203 int i;
204 for (i = 0; i < sizeof (laddr->in6.s6_addr); i++) {
205 if ((caddr->in6.s6_addr[i] & mask->in6.s6_addr[i]) !=
206 laddr->in6.s6_addr[i])
207 return (0);
208 }
209 return (1);
210 } else if (af == AF_INET) {
211 return ((caddr->in4.s_addr & mask->in4.s_addr) ==
212 laddr->in4.s_addr);
213 } else {
214 return (0);
215 }
216 }
217
218
219 static void
print_inaddr(char * string,sa_family_t af,inaddr_t * addr)220 print_inaddr(char *string, sa_family_t af, inaddr_t *addr) {
221
222 char buf[INET6_ADDRSTRLEN];
223
224 printf("%s %s %s\n",
225 string, (af == AF_INET6)?"AF_INET6":"AF_INET",
226 inet_ntop(af, (af == AF_INET6) ? (void *)&addr->in6 :
227 (void *)&addr->in4, buf, sizeof (buf)));
228 }
229